feat: idle animation
This commit is contained in:
@@ -15,3 +15,8 @@ pnpm i
|
||||
```shell
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
- [pixiv/ChatVRM](https://github.com/pixiv/ChatVRM)
|
||||
- [josephrocca/ChatVRM-js: A JS conversion/adaptation of parts of the ChatVRM (TypeScript) code for standalone use in OpenCharacters and elsewhere](https://github.com/josephrocca/ChatVRM-js)
|
||||
|
||||
@@ -15,3 +15,8 @@ pnpm i
|
||||
```shell
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
- [pixiv/ChatVRM](https://github.com/pixiv/ChatVRM)
|
||||
- [josephrocca/ChatVRM-js: A JS conversion/adaptation of parts of the ChatVRM (TypeScript) code for standalone use in OpenCharacters and elsewhere](https://github.com/josephrocca/ChatVRM-js)
|
||||
|
||||
@@ -54,6 +54,7 @@ words:
|
||||
- unhead
|
||||
- unocss
|
||||
- unplugin
|
||||
- vrma
|
||||
- vueuse
|
||||
- xsai
|
||||
ignoreWords: []
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
"@pixi/sprite": "6",
|
||||
"@pixi/ticker": "^6.5.10",
|
||||
"@pixi/utils": "6",
|
||||
"@pixiv/three-vrm": "^3.2.0",
|
||||
"@pixiv/three-vrm": "^3.3.0",
|
||||
"@pixiv/three-vrm-animation": "^3.3.0",
|
||||
"@pixiv/three-vrm-core": "^3.3.0",
|
||||
"@tresjs/cientos": "^4.0.3",
|
||||
"@tresjs/core": "^4.3.1",
|
||||
"@types/yauzl": "^2.10.3",
|
||||
|
||||
Binary file not shown.
@@ -324,7 +324,8 @@ onUnmounted(() => {
|
||||
/>
|
||||
<ThreeDScene
|
||||
v-else-if="stageView === '3d'"
|
||||
model="/assets/vrm/models/AvatarSample-A/AvatarSample_A.vrm"
|
||||
model="/assets/vrm/models/AvatarSample-B/AvatarSample_B.vrm"
|
||||
idle-animation="/assets/vrm/animations/idle_loop.vrma"
|
||||
w="50%" min-w="50% <lg:full" min-h="100 sm:100" h-full flex-1
|
||||
@error="console.error"
|
||||
/>
|
||||
|
||||
@@ -8,6 +8,7 @@ import VRMModel from './VRMModel.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
model: string
|
||||
idleAnimation: string
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -15,12 +16,12 @@ const emit = defineEmits<{
|
||||
(e: 'error', value: unknown): void
|
||||
}>()
|
||||
|
||||
const cameraPositionX = ref(0)
|
||||
const cameraPositionY = ref(0.1)
|
||||
const cameraPositionZ = ref(-1.5)
|
||||
const vrmModelPositionX = ref(0)
|
||||
const cameraPositionX = ref(-0.17)
|
||||
const cameraPositionY = ref(0)
|
||||
const cameraPositionZ = ref(-1)
|
||||
const vrmModelPositionX = ref(-0.18)
|
||||
const vrmModelPositionY = ref(-1.4)
|
||||
const vrmModelPositionZ = ref(-0.3)
|
||||
const vrmModelPositionZ = ref(-0.24)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -102,14 +103,16 @@ const vrmModelPositionZ = ref(-0.3)
|
||||
</div>
|
||||
<TresCanvas :alpha="true" :antialias="true" :width="canvasWidth" :height="canvasHeight">
|
||||
<TresPerspectiveCamera :position="[cameraPositionX, cameraPositionY, cameraPositionZ]" />
|
||||
<TresDirectionalLight :color="0xFFFFFF" :intensity="0.6" :position="[1, 1, 1]" />
|
||||
<OrbitControls />
|
||||
<VRMModel
|
||||
:model="props.model"
|
||||
:idle-animation="props.idleAnimation"
|
||||
:position="[vrmModelPositionX, vrmModelPositionY, vrmModelPositionZ]"
|
||||
@load-model-progress="(val) => emit('loadModelProgress', val)"
|
||||
@error="(val) => emit('error', val)"
|
||||
/>
|
||||
<TresAmbientLight :intensity="1" />
|
||||
<TresAmbientLight :color="0xFFFFFF" :intensity="0.4" />
|
||||
</TresCanvas>
|
||||
</Screen>
|
||||
</template>
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import type { VRMCore } from '@pixiv/three-vrm'
|
||||
import { VRMLoaderPlugin } from '@pixiv/three-vrm'
|
||||
import { useTresContext } from '@tresjs/core'
|
||||
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
|
||||
import type { VRMCore } from '@pixiv/three-vrm-core'
|
||||
import { useLoop, useTresContext } from '@tresjs/core'
|
||||
import { AnimationMixer } from 'three'
|
||||
import { clipFromVRMAnimation, loadVRMAnimation } from '~/composables/vrm/animation'
|
||||
import { loadVrm } from '~/composables/vrm/core'
|
||||
|
||||
const props = defineProps<{
|
||||
model: string
|
||||
idleAnimation: string
|
||||
loadAnimations?: string[]
|
||||
position: [number, number, number]
|
||||
}>()
|
||||
|
||||
@@ -14,43 +17,61 @@ const emit = defineEmits<{
|
||||
(e: 'error', value: unknown): void
|
||||
}>()
|
||||
|
||||
let vrm: VRMCore
|
||||
const vrm = ref<VRMCore>()
|
||||
const vrmAnimationMixer = ref<AnimationMixer>()
|
||||
const { scene } = useTresContext()
|
||||
const { onBeforeRender } = useLoop()
|
||||
|
||||
interface GLTFUserdata extends Record<string, any> {
|
||||
vrm: VRMCore
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
onMounted(async () => {
|
||||
if (!scene.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const loader = new GLTFLoader()
|
||||
loader.register(parser => new VRMLoaderPlugin(parser))
|
||||
loader.load(
|
||||
props.model,
|
||||
(gltf) => {
|
||||
const userData = gltf.userData as GLTFUserdata
|
||||
vrm = userData.vrm as VRMCore
|
||||
scene.value.add(vrm.scene)
|
||||
vrm.scene.position.set(...props.position)
|
||||
},
|
||||
progress => emit('loadModelProgress', Number.parseFloat((100.0 * (progress.loaded / progress.total)).toFixed(2))),
|
||||
error => emit('error', error),
|
||||
)
|
||||
try {
|
||||
const _vrm = await loadVrm(props.model, {
|
||||
scene: scene.value,
|
||||
lookAt: true,
|
||||
position: props.position,
|
||||
onProgress: progress => emit('loadModelProgress', Number.parseFloat((100.0 * (progress.loaded / progress.total)).toFixed(2))),
|
||||
})
|
||||
if (!_vrm) {
|
||||
console.warn('No VRM model loaded')
|
||||
return
|
||||
}
|
||||
|
||||
const animation = await loadVRMAnimation(props.idleAnimation)
|
||||
const clip = await clipFromVRMAnimation(_vrm, animation)
|
||||
if (!clip) {
|
||||
console.warn('No VRM animation loaded')
|
||||
return
|
||||
}
|
||||
|
||||
// play animation
|
||||
vrmAnimationMixer.value = new AnimationMixer(_vrm.scene)
|
||||
vrmAnimationMixer.value.clipAction(clip).play()
|
||||
|
||||
onBeforeRender(({ delta }) => {
|
||||
vrmAnimationMixer.value?.update(delta)
|
||||
vrm.value?.update(delta)
|
||||
})
|
||||
|
||||
vrm.value = _vrm
|
||||
}
|
||||
catch (err) {
|
||||
emit('error', err)
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (vrm) {
|
||||
if (vrm.value) {
|
||||
const { scene } = useTresContext()
|
||||
scene.value.remove(vrm.scene)
|
||||
scene.value.remove(vrm.value.scene)
|
||||
}
|
||||
})
|
||||
|
||||
watch(() => props.position, ([x, y, z]) => {
|
||||
if (vrm) {
|
||||
vrm.scene.position.set(x, y, z)
|
||||
if (vrm.value) {
|
||||
vrm.value.scene.position.set(x, y, z)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import type { VRMAnimation } from '@pixiv/three-vrm-animation'
|
||||
import type { VRMCore } from '@pixiv/three-vrm-core'
|
||||
import { createVRMAnimationClip } from '@pixiv/three-vrm-animation'
|
||||
import { useVRMLoader } from './loader'
|
||||
|
||||
export interface GLTFUserdata extends Record<string, any> {
|
||||
vrmAnimations: VRMAnimation[]
|
||||
}
|
||||
|
||||
export async function loadVRMAnimation(url: string) {
|
||||
const loader = useVRMLoader()
|
||||
|
||||
// load VRM Animation .vrma file
|
||||
const gltf = await loader.loadAsync(url)
|
||||
|
||||
const userData = gltf.userData as GLTFUserdata
|
||||
if (!userData.vrmAnimations) {
|
||||
console.warn('No VRM animations found in the .vrma file')
|
||||
return
|
||||
}
|
||||
if (userData.vrmAnimations.length === 0) {
|
||||
console.warn('No VRM animations found in the .vrma file')
|
||||
return
|
||||
}
|
||||
|
||||
return userData.vrmAnimations[0]
|
||||
}
|
||||
|
||||
export async function clipFromVRMAnimation(vrm?: VRMCore, animation?: VRMAnimation) {
|
||||
if (!vrm) {
|
||||
console.warn('No VRM found')
|
||||
return
|
||||
}
|
||||
if (!animation) {
|
||||
return
|
||||
}
|
||||
|
||||
// create animation clip
|
||||
return createVRMAnimationClip(animation, vrm)
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import type { Object3D, Scene } from 'three'
|
||||
import { type VRMCore, VRMUtils } from '@pixiv/three-vrm'
|
||||
|
||||
import { VRMLookAtQuaternionProxy } from '@pixiv/three-vrm-animation'
|
||||
import { useVRMLoader } from './loader'
|
||||
|
||||
interface GLTFUserdata extends Record<string, any> {
|
||||
vrmCore?: VRMCore
|
||||
}
|
||||
|
||||
export async function loadVrm(model: string, options?: {
|
||||
position?: [number, number, number]
|
||||
scene?: Scene
|
||||
lookAt?: boolean
|
||||
onProgress?: (progress: ProgressEvent<EventTarget>) => void | Promise<void>
|
||||
}): Promise<VRMCore | undefined> {
|
||||
const loader = useVRMLoader()
|
||||
const gltf = await loader.loadAsync(model, progress => options?.onProgress?.(progress))
|
||||
|
||||
const userData = gltf.userData as GLTFUserdata
|
||||
if (!userData.vrm) {
|
||||
return
|
||||
}
|
||||
|
||||
const _vrm = userData.vrm
|
||||
|
||||
// calling these functions greatly improves the performance
|
||||
VRMUtils.removeUnnecessaryVertices(_vrm.scene)
|
||||
VRMUtils.combineSkeletons(_vrm.scene)
|
||||
|
||||
// Disable frustum culling
|
||||
_vrm.scene.traverse((object: Object3D) => {
|
||||
object.frustumCulled = false
|
||||
})
|
||||
|
||||
// Add look at quaternion proxy to the VRM; which is needed to play the look at animation
|
||||
if (options?.lookAt && _vrm.lookAt) {
|
||||
const lookAtQuatProxy = new VRMLookAtQuaternionProxy(_vrm.lookAt)
|
||||
lookAtQuatProxy.name = 'lookAtQuaternionProxy'
|
||||
_vrm.scene.add(lookAtQuatProxy)
|
||||
}
|
||||
|
||||
// Add to scene
|
||||
if (options?.scene)
|
||||
options.scene.add(_vrm.scene)
|
||||
|
||||
// Set position
|
||||
if (options?.position)
|
||||
_vrm.scene.position.set(...options.position)
|
||||
|
||||
return _vrm
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { VRMLoaderPlugin } from '@pixiv/three-vrm'
|
||||
import { VRMAnimationLoaderPlugin } from '@pixiv/three-vrm-animation'
|
||||
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
|
||||
|
||||
let loader: GLTFLoader
|
||||
|
||||
export function useVRMLoader() {
|
||||
if (loader) {
|
||||
return loader
|
||||
}
|
||||
|
||||
loader = new GLTFLoader()
|
||||
|
||||
loader.crossOrigin = 'anonymous'
|
||||
loader.register(parser => new VRMLoaderPlugin(parser))
|
||||
loader.register(parser => new VRMAnimationLoaderPlugin(parser))
|
||||
|
||||
return loader
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
export interface AudioManagerType {
|
||||
audioContext: AudioContext
|
||||
analyser: AnalyserNode
|
||||
dataBuffer: Float32Array
|
||||
frameId: number | null
|
||||
onVolumeChange?: (volume: number) => void
|
||||
}
|
||||
|
||||
export function createAudioManager(): AudioManagerType {
|
||||
const audioContext = new AudioContext()
|
||||
const analyser = audioContext.createAnalyser()
|
||||
const dataBuffer = new Float32Array(2048)
|
||||
|
||||
// Connect analyser to destination
|
||||
analyser.connect(audioContext.destination)
|
||||
|
||||
return {
|
||||
audioContext,
|
||||
analyser,
|
||||
dataBuffer,
|
||||
frameId: null,
|
||||
onVolumeChange: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
function calculateVolume(manager: AudioManagerType): number {
|
||||
manager.analyser.getFloatTimeDomainData(manager.dataBuffer)
|
||||
|
||||
// Find peak volume
|
||||
let volume = 0.0
|
||||
for (let i = 0; i < manager.dataBuffer.length; i++) {
|
||||
volume = Math.max(volume, Math.abs(manager.dataBuffer[i]))
|
||||
}
|
||||
|
||||
// Apply sigmoid normalization (from pixiv implementation)
|
||||
volume = 1 / (1 + Math.exp(-45 * volume + 5))
|
||||
return volume < 0.1 ? 0 : volume
|
||||
}
|
||||
|
||||
function updateFrame(manager: AudioManagerType) {
|
||||
if (manager.onVolumeChange) {
|
||||
manager.onVolumeChange(calculateVolume(manager))
|
||||
}
|
||||
manager.frameId = requestAnimationFrame(() => updateFrame(manager))
|
||||
}
|
||||
|
||||
export async function playAudio(manager: AudioManagerType, source: ArrayBuffer | string): Promise<void> {
|
||||
try {
|
||||
const buffer = typeof source === 'string'
|
||||
? await (await fetch(source)).arrayBuffer()
|
||||
: source
|
||||
|
||||
const audioBuffer = await manager.audioContext.decodeAudioData(buffer)
|
||||
const bufferSource = manager.audioContext.createBufferSource()
|
||||
|
||||
bufferSource.buffer = audioBuffer
|
||||
bufferSource.connect(manager.analyser)
|
||||
bufferSource.start()
|
||||
|
||||
return new Promise((resolve) => {
|
||||
bufferSource.onended = () => resolve()
|
||||
})
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error playing audio:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export function startVolumeTracking(manager: AudioManagerType, callback: (volume: number) => void) {
|
||||
manager.onVolumeChange = callback
|
||||
manager.audioContext.resume()
|
||||
updateFrame(manager)
|
||||
}
|
||||
|
||||
export function stopVolumeTracking(manager: AudioManagerType) {
|
||||
if (manager.frameId) {
|
||||
cancelAnimationFrame(manager.frameId)
|
||||
manager.frameId = null
|
||||
}
|
||||
manager.onVolumeChange = undefined
|
||||
}
|
||||
|
||||
export function disposeAudioManager(manager: AudioManagerType) {
|
||||
stopVolumeTracking(manager)
|
||||
manager.audioContext.close()
|
||||
}
|
||||
@@ -20,10 +20,7 @@ export const useLLM = defineStore('llm', () => {
|
||||
|
||||
async function models(apiUrl: string, apiKey: string) {
|
||||
if (apiUrl === '') {
|
||||
return {
|
||||
data: [],
|
||||
object: '',
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -34,10 +31,7 @@ export const useLLM = defineStore('llm', () => {
|
||||
}
|
||||
catch (err) {
|
||||
if (String(err).includes(`Failed to construct 'URL': Invalid URL`)) {
|
||||
return {
|
||||
data: [],
|
||||
object: '',
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
throw err
|
||||
|
||||
Generated
+91
-61
@@ -142,8 +142,14 @@ importers:
|
||||
specifier: '6'
|
||||
version: 6.5.10(@pixi/constants@6.5.10)(@pixi/settings@6.5.10(@pixi/constants@6.5.10))
|
||||
'@pixiv/three-vrm':
|
||||
specifier: ^3.2.0
|
||||
version: 3.2.0(three@0.171.0)
|
||||
specifier: ^3.3.0
|
||||
version: 3.3.0(three@0.171.0)
|
||||
'@pixiv/three-vrm-animation':
|
||||
specifier: ^3.3.0
|
||||
version: 3.3.0(three@0.171.0)
|
||||
'@pixiv/three-vrm-core':
|
||||
specifier: ^3.3.0
|
||||
version: 3.3.0(three@0.171.0)
|
||||
'@tresjs/cientos':
|
||||
specifier: ^4.0.3
|
||||
version: 4.0.3(@tresjs/core@4.3.1(three@0.171.0)(vue@3.5.13(typescript@5.7.2)))(@types/three@0.170.0)(react@18.3.1)(three@0.171.0)(vue@3.5.13(typescript@5.7.2))
|
||||
@@ -1898,61 +1904,72 @@ packages:
|
||||
'@pixi/constants': 6.5.10
|
||||
'@pixi/settings': 6.5.10
|
||||
|
||||
'@pixiv/three-vrm-core@3.2.0':
|
||||
resolution: {integrity: sha512-S/vEMSouVsbS7yv+PToK+r6UOWm0uR6d3djPOVSeGZKXbXjoNWZc5btjVWL+FAE1/rtdxXO9cMw0kBvI43Rujw==}
|
||||
'@pixiv/three-vrm-animation@3.3.0':
|
||||
resolution: {integrity: sha512-hv+Wq+4BVYZMw4g1IIOPqMyVewi+5gt9BO5T8STdd/M93dJnrwV1TTRhWhhRbwWVWYpKKX91dDrmjXJK5tKcJQ==}
|
||||
peerDependencies:
|
||||
three: '>=0.137'
|
||||
|
||||
'@pixiv/three-vrm-materials-hdr-emissive-multiplier@3.2.0':
|
||||
resolution: {integrity: sha512-3Ai1ENdNiVnsxfzzXSKDCyT+w6awY7sHjoX6fKKnQ9tn2WGhxY596VUGDp/WyGDY2BM4NkSCUVd6qSGNEeEX6g==}
|
||||
'@pixiv/three-vrm-core@3.3.0':
|
||||
resolution: {integrity: sha512-AeeuErYF+jxhqJvoBuuc6pqqcegZMSgkLLE+huMHGHasMuHjQt2RAslcANLfpHLn65WEN4GmCtqBw2IWrxFiBQ==}
|
||||
peerDependencies:
|
||||
three: '>=0.137'
|
||||
|
||||
'@pixiv/three-vrm-materials-mtoon@3.2.0':
|
||||
resolution: {integrity: sha512-wZollYD+cnTCdCJyrSuIGC1zVqXrZl2zWEzzwZ0+955/+UUltxYAHdFmSXpoChYNX89FFiIzIdfoARdYHMqNzw==}
|
||||
'@pixiv/three-vrm-materials-hdr-emissive-multiplier@3.3.0':
|
||||
resolution: {integrity: sha512-aiCAkkZtT4/RGBO75DNEqeIWjdbEg//UUU+uYls2cnNucGa6td9zFXMkQ2S7yj+38/DFmKAvOSBWKyI6Q6e7EQ==}
|
||||
peerDependencies:
|
||||
three: '>=0.137'
|
||||
|
||||
'@pixiv/three-vrm-materials-v0compat@3.2.0':
|
||||
resolution: {integrity: sha512-z1qjQUjqTWWE7f/7vm2QzluL7e8fcSi/q6RMjpmsXQurfXdH06j43IWn5Lp8E9O16ZHbKw9HqBN8YkBv1qpgmg==}
|
||||
'@pixiv/three-vrm-materials-mtoon@3.3.0':
|
||||
resolution: {integrity: sha512-DvUeFidvY74fau/L+Lhe5sxvC5ri5eHK7SF700eYosJIWvDY/KgVkCjc3jCNqrAOp0OBGGCYjcvRDh23eVUO0Q==}
|
||||
peerDependencies:
|
||||
three: '>=0.137'
|
||||
|
||||
'@pixiv/three-vrm-node-constraint@3.2.0':
|
||||
resolution: {integrity: sha512-NQMD3KQJx2i6CEGnabcOdeS8/m0KUrvOp4N4iEdFM0LRd/34zmasHBqLROlhFMG7tGan858wZ1HqyWnKOIc6Rw==}
|
||||
'@pixiv/three-vrm-materials-v0compat@3.3.0':
|
||||
resolution: {integrity: sha512-Ot0sj5Hfacw4258TDBFXOlWvI35B9YLW1wJ6WnqUZdlQd9t7dzD0o0NommOofVn40bRmIuI5Bxd5N9j0WxBxzg==}
|
||||
peerDependencies:
|
||||
three: '>=0.137'
|
||||
|
||||
'@pixiv/three-vrm-springbone@3.2.0':
|
||||
resolution: {integrity: sha512-kMdHQLgHvhwNj/5WAPh6n+Q/Vva+9OgMFAzBtILoMKxfusS/LyDc7Du2KUaHU8huyB/ucvHSEan0rTEH2mz1dQ==}
|
||||
'@pixiv/three-vrm-node-constraint@3.3.0':
|
||||
resolution: {integrity: sha512-XvbS1sFJsuCfnboxEKhV2NltT929k3/VSYkQLRvw+uz6oVPUJHZ3w6cK8E6pvD9WKuBefDf+AQZQpn5PCRO25w==}
|
||||
peerDependencies:
|
||||
three: '>=0.137'
|
||||
|
||||
'@pixiv/three-vrm@3.2.0':
|
||||
resolution: {integrity: sha512-M/t9xRK3v0SYsY1G4S3MMcQimovrQQBn4rcM+Ffh3z/gZTOGeivfRuGWhjZhxWY+ACoZ9X8HcpdvGbNsTVPrjQ==}
|
||||
'@pixiv/three-vrm-springbone@3.3.0':
|
||||
resolution: {integrity: sha512-aLzRXJukck7G8g/lm2Asob1N0QPjgYGoGU4YA9IgpdBFIz07S3CNDww/Lv/wmLJahyZqQCdJvghSr2X5yG8EtQ==}
|
||||
peerDependencies:
|
||||
three: '>=0.137'
|
||||
|
||||
'@pixiv/types-vrm-0.0@3.2.0':
|
||||
resolution: {integrity: sha512-hxj3Z1V8KqEfeg11+6Q0groz7Rdpg/WL0PsoEFvPY1U06QD2SZFIdxLsSh2yRfMiwL1DhZJi614PoaHMaMiVhQ==}
|
||||
'@pixiv/three-vrm@3.3.0':
|
||||
resolution: {integrity: sha512-zPr3di6BYeZzhMf3WOTR5uG/o88ZtLzUOar6n2VtTukY8IKX05rbBIoAwcjqgxXA7kn+CEverKN1tQXuYQAHKw==}
|
||||
peerDependencies:
|
||||
three: '>=0.137'
|
||||
|
||||
'@pixiv/types-vrmc-materials-hdr-emissive-multiplier-1.0@3.2.0':
|
||||
resolution: {integrity: sha512-xWiWtUP7IdVAT4JFjSD797TaX1fD38TwBucahYjT8Yq2b20frRQJ+/FrCG1cJ83Ja02PDQGtLY1VKy4lZ6c4Xg==}
|
||||
'@pixiv/types-vrm-0.0@3.3.0':
|
||||
resolution: {integrity: sha512-3AC+hR24O9yEMxoKkGiEVvj8zydh/poy5ZR6FieyvbRsKTJ/+Z8WJgTKnO7hJHkvPOntYznhsWJqjj/YG9kTLw==}
|
||||
|
||||
'@pixiv/types-vrmc-materials-mtoon-1.0@3.2.0':
|
||||
resolution: {integrity: sha512-p6sWf6uzce3cSc8KiStSyB33GPwDEYPFjRxDKNpepe64i9wuXVqdtJNvh0WOWrb85VLxOfq78XAWeJIcdUF2Ww==}
|
||||
'@pixiv/types-vrmc-materials-hdr-emissive-multiplier-1.0@3.3.0':
|
||||
resolution: {integrity: sha512-Q6PCgnt0Kl5v+DI8VAueJ4qyTgQjf186SpWa91m7ZTPIX7hsdOeXly7cO8n64UBnEgihcgWoBS8mhMOLbHBxVg==}
|
||||
|
||||
'@pixiv/types-vrmc-node-constraint-1.0@3.2.0':
|
||||
resolution: {integrity: sha512-wZT86mIHDBV7GefnsdsEGwT6IDxZISNHhbaCAjmoyZNZz+mO/J65WOrdbiMSlTgFXxyiBVge7h4WplLMsZCuhA==}
|
||||
'@pixiv/types-vrmc-materials-mtoon-1.0@3.3.0':
|
||||
resolution: {integrity: sha512-I0tJIMbs6yaHoMu6cw/bZxABk1kieWKv0Gu6JhECfN8IAo+WM0sYPOYMfzEkbxulpDUA8JIo0Kfn5s1B2Maf2A==}
|
||||
|
||||
'@pixiv/types-vrmc-springbone-1.0@3.2.0':
|
||||
resolution: {integrity: sha512-ifnnbtGQiVTJF51MRhNPGfpdZMePBlEKDpOJe83n0S0XmVtHahbspWelGxiecDbPfYUMElqpIBhnDZmai4fT5Q==}
|
||||
'@pixiv/types-vrmc-node-constraint-1.0@3.3.0':
|
||||
resolution: {integrity: sha512-y6Ae2OFZQcY/ymxJqNT6lAT8Jo5kdDVfDtY2UvjtTlQ5tE0IbUv7HaBXVIX8CHurUWCy0kyV51iwSQ1Sdbw0bA==}
|
||||
|
||||
'@pixiv/types-vrmc-springbone-extended-collider-1.0@3.2.0':
|
||||
resolution: {integrity: sha512-tImS5zKDMT9mliAyAaUmjs9susVj+mJiV8ZK2G2EOcchkt0SlD+kcrfpJPFxng5zfux/EFpIHUbXRFL9wqUOrQ==}
|
||||
'@pixiv/types-vrmc-springbone-1.0@3.3.0':
|
||||
resolution: {integrity: sha512-IjyV9QyxcyohIji5AegC4OS2VMsSKEDA+1ddq39KBPtTPtjvSjGU7ppvNBrWXYhyX0s0OCOsdqM0SmTCZVp/kw==}
|
||||
|
||||
'@pixiv/types-vrmc-vrm-1.0@3.2.0':
|
||||
resolution: {integrity: sha512-XvqfRK90DIQl+6PxqIi0svEmjilFzpOOOdzGR6zh0tNV0yBV4cemLSs9v6BouDMtPt4aZ69dQR2ApA8VMbaV4w==}
|
||||
'@pixiv/types-vrmc-springbone-extended-collider-1.0@3.3.0':
|
||||
resolution: {integrity: sha512-5iBqq3S1MsOtKj5XVVbmx0z4UKO2muUSkamzI+Y2pErQsJyssu9SZBewPyC+aFG8XPk7wUbenQ5MxWHWOPFnFw==}
|
||||
|
||||
'@pixiv/types-vrmc-vrm-1.0@2.0.3':
|
||||
resolution: {integrity: sha512-RMP34Bk1qLFQv/CRB1Zqvn2qMFfWQfP2Hms5QrrfoBsW9XroZdEe0zPLNbGmUPYh4F7VtBb+B7+RCuymRtpehA==}
|
||||
|
||||
'@pixiv/types-vrmc-vrm-1.0@3.3.0':
|
||||
resolution: {integrity: sha512-4JJizAfGFpyyL+IGMv22z5ORqJ2M3sFgYK0ZRF/ZjOmG8aaQHqh9zFx5KYXdudbT3N95Qo+Nl8/nLN5pwMFEoA==}
|
||||
|
||||
'@pixiv/types-vrmc-vrm-animation-1.0@3.3.0':
|
||||
resolution: {integrity: sha512-jgmiBPldGmrWbn0EUMt51bb8cSZqBw43bUYHcQfTar70OyVC1h25aV1B34nTNzl1IDPX2QnV2FdOPASpRtRYAA==}
|
||||
|
||||
'@pkgr/core@0.1.0':
|
||||
resolution: {integrity: sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==}
|
||||
@@ -8350,64 +8367,77 @@ snapshots:
|
||||
eventemitter3: 3.1.2
|
||||
url: 0.11.4
|
||||
|
||||
'@pixiv/three-vrm-core@3.2.0(three@0.171.0)':
|
||||
'@pixiv/three-vrm-animation@3.3.0(three@0.171.0)':
|
||||
dependencies:
|
||||
'@pixiv/types-vrm-0.0': 3.2.0
|
||||
'@pixiv/types-vrmc-vrm-1.0': 3.2.0
|
||||
'@pixiv/three-vrm-core': 3.3.0(three@0.171.0)
|
||||
'@pixiv/types-vrmc-vrm-1.0': 3.3.0
|
||||
'@pixiv/types-vrmc-vrm-animation-1.0': 3.3.0
|
||||
three: 0.171.0
|
||||
|
||||
'@pixiv/three-vrm-materials-hdr-emissive-multiplier@3.2.0(three@0.171.0)':
|
||||
'@pixiv/three-vrm-core@3.3.0(three@0.171.0)':
|
||||
dependencies:
|
||||
'@pixiv/types-vrmc-materials-hdr-emissive-multiplier-1.0': 3.2.0
|
||||
'@pixiv/types-vrm-0.0': 3.3.0
|
||||
'@pixiv/types-vrmc-vrm-1.0': 3.3.0
|
||||
three: 0.171.0
|
||||
|
||||
'@pixiv/three-vrm-materials-mtoon@3.2.0(three@0.171.0)':
|
||||
'@pixiv/three-vrm-materials-hdr-emissive-multiplier@3.3.0(three@0.171.0)':
|
||||
dependencies:
|
||||
'@pixiv/types-vrm-0.0': 3.2.0
|
||||
'@pixiv/types-vrmc-materials-mtoon-1.0': 3.2.0
|
||||
'@pixiv/types-vrmc-materials-hdr-emissive-multiplier-1.0': 3.3.0
|
||||
three: 0.171.0
|
||||
|
||||
'@pixiv/three-vrm-materials-v0compat@3.2.0(three@0.171.0)':
|
||||
'@pixiv/three-vrm-materials-mtoon@3.3.0(three@0.171.0)':
|
||||
dependencies:
|
||||
'@pixiv/types-vrm-0.0': 3.2.0
|
||||
'@pixiv/types-vrmc-materials-mtoon-1.0': 3.2.0
|
||||
'@pixiv/types-vrm-0.0': 3.3.0
|
||||
'@pixiv/types-vrmc-materials-mtoon-1.0': 3.3.0
|
||||
three: 0.171.0
|
||||
|
||||
'@pixiv/three-vrm-node-constraint@3.2.0(three@0.171.0)':
|
||||
'@pixiv/three-vrm-materials-v0compat@3.3.0(three@0.171.0)':
|
||||
dependencies:
|
||||
'@pixiv/types-vrmc-node-constraint-1.0': 3.2.0
|
||||
'@pixiv/types-vrm-0.0': 3.3.0
|
||||
'@pixiv/types-vrmc-materials-mtoon-1.0': 3.3.0
|
||||
three: 0.171.0
|
||||
|
||||
'@pixiv/three-vrm-springbone@3.2.0(three@0.171.0)':
|
||||
'@pixiv/three-vrm-node-constraint@3.3.0(three@0.171.0)':
|
||||
dependencies:
|
||||
'@pixiv/types-vrm-0.0': 3.2.0
|
||||
'@pixiv/types-vrmc-springbone-1.0': 3.2.0
|
||||
'@pixiv/types-vrmc-springbone-extended-collider-1.0': 3.2.0
|
||||
'@pixiv/types-vrmc-node-constraint-1.0': 3.3.0
|
||||
three: 0.171.0
|
||||
|
||||
'@pixiv/three-vrm@3.2.0(three@0.171.0)':
|
||||
'@pixiv/three-vrm-springbone@3.3.0(three@0.171.0)':
|
||||
dependencies:
|
||||
'@pixiv/three-vrm-core': 3.2.0(three@0.171.0)
|
||||
'@pixiv/three-vrm-materials-hdr-emissive-multiplier': 3.2.0(three@0.171.0)
|
||||
'@pixiv/three-vrm-materials-mtoon': 3.2.0(three@0.171.0)
|
||||
'@pixiv/three-vrm-materials-v0compat': 3.2.0(three@0.171.0)
|
||||
'@pixiv/three-vrm-node-constraint': 3.2.0(three@0.171.0)
|
||||
'@pixiv/three-vrm-springbone': 3.2.0(three@0.171.0)
|
||||
'@pixiv/types-vrm-0.0': 3.3.0
|
||||
'@pixiv/types-vrmc-springbone-1.0': 3.3.0
|
||||
'@pixiv/types-vrmc-springbone-extended-collider-1.0': 3.3.0
|
||||
three: 0.171.0
|
||||
|
||||
'@pixiv/types-vrm-0.0@3.2.0': {}
|
||||
'@pixiv/three-vrm@3.3.0(three@0.171.0)':
|
||||
dependencies:
|
||||
'@pixiv/three-vrm-core': 3.3.0(three@0.171.0)
|
||||
'@pixiv/three-vrm-materials-hdr-emissive-multiplier': 3.3.0(three@0.171.0)
|
||||
'@pixiv/three-vrm-materials-mtoon': 3.3.0(three@0.171.0)
|
||||
'@pixiv/three-vrm-materials-v0compat': 3.3.0(three@0.171.0)
|
||||
'@pixiv/three-vrm-node-constraint': 3.3.0(three@0.171.0)
|
||||
'@pixiv/three-vrm-springbone': 3.3.0(three@0.171.0)
|
||||
three: 0.171.0
|
||||
|
||||
'@pixiv/types-vrmc-materials-hdr-emissive-multiplier-1.0@3.2.0': {}
|
||||
'@pixiv/types-vrm-0.0@3.3.0': {}
|
||||
|
||||
'@pixiv/types-vrmc-materials-mtoon-1.0@3.2.0': {}
|
||||
'@pixiv/types-vrmc-materials-hdr-emissive-multiplier-1.0@3.3.0': {}
|
||||
|
||||
'@pixiv/types-vrmc-node-constraint-1.0@3.2.0': {}
|
||||
'@pixiv/types-vrmc-materials-mtoon-1.0@3.3.0': {}
|
||||
|
||||
'@pixiv/types-vrmc-springbone-1.0@3.2.0': {}
|
||||
'@pixiv/types-vrmc-node-constraint-1.0@3.3.0': {}
|
||||
|
||||
'@pixiv/types-vrmc-springbone-extended-collider-1.0@3.2.0': {}
|
||||
'@pixiv/types-vrmc-springbone-1.0@3.3.0': {}
|
||||
|
||||
'@pixiv/types-vrmc-vrm-1.0@3.2.0': {}
|
||||
'@pixiv/types-vrmc-springbone-extended-collider-1.0@3.3.0': {}
|
||||
|
||||
'@pixiv/types-vrmc-vrm-1.0@2.0.3': {}
|
||||
|
||||
'@pixiv/types-vrmc-vrm-1.0@3.3.0': {}
|
||||
|
||||
'@pixiv/types-vrmc-vrm-animation-1.0@3.3.0':
|
||||
dependencies:
|
||||
'@pixiv/types-vrmc-vrm-1.0': 2.0.3
|
||||
|
||||
'@pkgr/core@0.1.0': {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user