spoint 0.1.43 → 0.1.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/LoadingManager.js +3 -1
- package/client/animation.js +15 -13
- package/client/app.js +14 -6
- package/package.json +1 -1
package/client/LoadingManager.js
CHANGED
|
@@ -79,6 +79,8 @@ export class LoadingManager extends EventTarget {
|
|
|
79
79
|
const response = await fetch(url)
|
|
80
80
|
if (!response.ok) throw new Error(`HTTP ${response.status}`)
|
|
81
81
|
const contentLength = parseInt(response.headers.get('content-length') || '0', 10)
|
|
82
|
+
const isGzip = (response.headers.get('content-encoding') || '').includes('gzip')
|
|
83
|
+
const useTotal = contentLength > 0 && !isGzip
|
|
82
84
|
const reader = response.body.getReader()
|
|
83
85
|
const chunks = []
|
|
84
86
|
let receivedLength = 0
|
|
@@ -88,7 +90,7 @@ export class LoadingManager extends EventTarget {
|
|
|
88
90
|
if (done) break
|
|
89
91
|
chunks.push(value)
|
|
90
92
|
receivedLength += value.length
|
|
91
|
-
if (
|
|
93
|
+
if (useTotal) {
|
|
92
94
|
this.updateProgress(receivedLength, contentLength)
|
|
93
95
|
}
|
|
94
96
|
}
|
package/client/animation.js
CHANGED
|
@@ -123,21 +123,23 @@ function normalizeClips(gltf, vrmVersion, vrmHumanoid) {
|
|
|
123
123
|
return clips
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
let
|
|
127
|
-
let
|
|
126
|
+
let _gltfPromise = null
|
|
127
|
+
let _normalizedCache = null
|
|
128
|
+
|
|
129
|
+
export function preloadAnimationLibrary() {
|
|
130
|
+
if (_gltfPromise) return _gltfPromise
|
|
131
|
+
_gltfPromise = new GLTFLoader().loadAsync('/anim-lib.glb')
|
|
132
|
+
return _gltfPromise
|
|
133
|
+
}
|
|
128
134
|
|
|
129
135
|
export async function loadAnimationLibrary(vrmVersion, vrmHumanoid) {
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
_animLibCache = { normalizedClips }
|
|
138
|
-
return _animLibCache
|
|
139
|
-
})()
|
|
140
|
-
return _animLibPromise
|
|
136
|
+
if (_normalizedCache) return _normalizedCache
|
|
137
|
+
const gltf = await preloadAnimationLibrary()
|
|
138
|
+
if (_normalizedCache) return _normalizedCache
|
|
139
|
+
const normalizedClips = normalizeClips(gltf, vrmVersion || '1', vrmHumanoid)
|
|
140
|
+
console.log(`[anim] Loaded animation library (${normalizedClips.size} clips):`, [...normalizedClips.keys()])
|
|
141
|
+
_normalizedCache = { normalizedClips }
|
|
142
|
+
return _normalizedCache
|
|
141
143
|
}
|
|
142
144
|
|
|
143
145
|
export function createPlayerAnimator(vrm, allClips, vrmVersion, animConfig = {}) {
|
package/client/app.js
CHANGED
|
@@ -9,7 +9,7 @@ import { VRMLoaderPlugin, VRMUtils } from '@pixiv/three-vrm'
|
|
|
9
9
|
import { PhysicsNetworkClient, InputHandler, MSG } from '/src/index.client.js'
|
|
10
10
|
import { createElement, applyDiff } from 'webjsx'
|
|
11
11
|
import { createCameraController } from './camera.js'
|
|
12
|
-
import { loadAnimationLibrary, createPlayerAnimator } from './animation.js'
|
|
12
|
+
import { loadAnimationLibrary, preloadAnimationLibrary, createPlayerAnimator } from './animation.js'
|
|
13
13
|
import { initFacialSystem } from './facial-animation.js'
|
|
14
14
|
import { VRButton } from 'three/addons/webxr/VRButton.js'
|
|
15
15
|
import { XRControllerModelFactory } from 'three/addons/webxr/XRControllerModelFactory.js'
|
|
@@ -713,16 +713,15 @@ function detectVrmVersion(buffer) {
|
|
|
713
713
|
|
|
714
714
|
function initAssets(playerModelUrl) {
|
|
715
715
|
loadingMgr.setStage('DOWNLOAD')
|
|
716
|
-
|
|
716
|
+
preloadAnimationLibrary()
|
|
717
717
|
assetsReady = loadingMgr.fetchWithProgress(playerModelUrl).then(async b => {
|
|
718
718
|
vrmBuffer = b
|
|
719
719
|
loadingMgr.setStage('PROCESS')
|
|
720
|
-
animAssets = await
|
|
720
|
+
animAssets = await loadAnimationLibrary(detectVrmVersion(b), null)
|
|
721
721
|
assetsLoaded = true
|
|
722
722
|
checkAllLoaded()
|
|
723
723
|
}).catch(err => {
|
|
724
724
|
console.warn('[assets] player model unavailable:', err.message)
|
|
725
|
-
animLibPromise.then(r => { animAssets = r }).catch(() => {})
|
|
726
725
|
assetsLoaded = true
|
|
727
726
|
checkAllLoaded()
|
|
728
727
|
})
|
|
@@ -978,8 +977,9 @@ function loadEntityModel(entityId, entityState) {
|
|
|
978
977
|
fitShadowFrustum()
|
|
979
978
|
pendingLoads.delete(entityId)
|
|
980
979
|
if (!environmentLoaded) { environmentLoaded = true; checkAllLoaded() }
|
|
980
|
+
if (firstSnapshotEntityPending.has(entityId)) { firstSnapshotEntityPending.delete(entityId); if (firstSnapshotEntityPending.size === 0) checkAllLoaded() }
|
|
981
981
|
if (loadingScreenHidden) renderer.compileAsync(scene, camera).catch(() => renderer.compile(scene, camera))
|
|
982
|
-
}, (progress) => { if (progress.total > 0) console.log('[gltf]', url, Math.round(progress.loaded / progress.total * 100) + '%') }, (err) => { console.error('[gltf]', url, err); pendingLoads.delete(entityId) })
|
|
982
|
+
}, (progress) => { if (progress.total > 0) console.log('[gltf]', url, Math.round(Math.min(progress.loaded, progress.total) / progress.total * 100) + '%') }, (err) => { console.error('[gltf]', url, err); pendingLoads.delete(entityId); if (firstSnapshotEntityPending.has(entityId)) { firstSnapshotEntityPending.delete(entityId); if (firstSnapshotEntityPending.size === 0) checkAllLoaded() } })
|
|
983
983
|
}
|
|
984
984
|
|
|
985
985
|
function renderAppUI(state) {
|
|
@@ -1027,7 +1027,13 @@ const client = new PhysicsNetworkClient({
|
|
|
1027
1027
|
}
|
|
1028
1028
|
rebuildEntityHierarchy(smoothState.entities)
|
|
1029
1029
|
latestState = state
|
|
1030
|
-
if (!firstSnapshotReceived) {
|
|
1030
|
+
if (!firstSnapshotReceived) {
|
|
1031
|
+
firstSnapshotReceived = true
|
|
1032
|
+
for (const e of smoothState.entities) {
|
|
1033
|
+
if (e.model && !entityMeshes.has(e.id)) firstSnapshotEntityPending.add(e.id)
|
|
1034
|
+
}
|
|
1035
|
+
checkAllLoaded()
|
|
1036
|
+
}
|
|
1031
1037
|
},
|
|
1032
1038
|
onPlayerJoined: (id) => { if (!playerMeshes.has(id)) createPlayerVRM(id) },
|
|
1033
1039
|
onPlayerLeft: (id) => removePlayerMesh(id),
|
|
@@ -1092,6 +1098,7 @@ let inputLoopId = null
|
|
|
1092
1098
|
let loadingScreenHidden = false
|
|
1093
1099
|
let environmentLoaded = false
|
|
1094
1100
|
let firstSnapshotReceived = false
|
|
1101
|
+
const firstSnapshotEntityPending = new Set()
|
|
1095
1102
|
let lastShootState = false
|
|
1096
1103
|
let lastHealth = 100
|
|
1097
1104
|
|
|
@@ -1124,6 +1131,7 @@ function checkAllLoaded() {
|
|
|
1124
1131
|
if (!assetsLoaded) return
|
|
1125
1132
|
if (!environmentLoaded) return
|
|
1126
1133
|
if (!firstSnapshotReceived) return
|
|
1134
|
+
if (firstSnapshotEntityPending.size > 0) return
|
|
1127
1135
|
loadingMgr.setStage('INIT')
|
|
1128
1136
|
loadingMgr.complete()
|
|
1129
1137
|
loadingScreenHidden = true
|