|
|
@ -17,6 +17,8 @@ import { HEIGHT } from '../Player'
|
|
|
|
import api, { State, Transform } from '../../store'
|
|
|
|
import api, { State, Transform } from '../../store'
|
|
|
|
import { Color } from 'three/src/math/Color'
|
|
|
|
import { Color } from 'three/src/math/Color'
|
|
|
|
import { MeshNormalMaterial } from 'three/src/materials/MeshNormalMaterial'
|
|
|
|
import { MeshNormalMaterial } from 'three/src/materials/MeshNormalMaterial'
|
|
|
|
|
|
|
|
import { Object3D } from 'three/src/core/Object3D'
|
|
|
|
|
|
|
|
import { SkinnedMesh } from 'three/src/objects/SkinnedMesh'
|
|
|
|
|
|
|
|
|
|
|
|
type GLTFResult = GLTF & {
|
|
|
|
type GLTFResult = GLTF & {
|
|
|
|
nodes: {
|
|
|
|
nodes: {
|
|
|
@ -51,11 +53,12 @@ const Human: React.FC<JSX.IntrinsicElements['group'] & { id: number }> = ({
|
|
|
|
const gltf = useGLTF('/model/human.glb') as GLTFResult
|
|
|
|
const gltf = useGLTF('/model/human.glb') as GLTFResult
|
|
|
|
const currentAnimation = useRef<ActionName>('idle')
|
|
|
|
const currentAnimation = useRef<ActionName>('idle')
|
|
|
|
|
|
|
|
|
|
|
|
const { scene, animations } = cloneGltf(gltf)
|
|
|
|
const { scene, animations } = cloneGltf(gltf as GLTFResult)
|
|
|
|
|
|
|
|
|
|
|
|
const [nodes] = useState(() => {
|
|
|
|
const [nodes] = useState<Record<string, SkinnedMesh[]>>(() => {
|
|
|
|
const n = {}
|
|
|
|
const n = {}
|
|
|
|
scene.children[0].children.forEach((child) => {
|
|
|
|
scene.children[0].children.forEach((child: Object3D) => {
|
|
|
|
|
|
|
|
//@ts-ignore
|
|
|
|
n[child.name] = child
|
|
|
|
n[child.name] = child
|
|
|
|
})
|
|
|
|
})
|
|
|
|
return n
|
|
|
|
return n
|
|
|
@ -88,11 +91,12 @@ const Human: React.FC<JSX.IntrinsicElements['group'] & { id: number }> = ({
|
|
|
|
}, [])
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
|
|
|
|
const actions = useRef<GLTFActions>()
|
|
|
|
const actions = useRef<GLTFActions>()
|
|
|
|
|
|
|
|
//@ts-ignore
|
|
|
|
const [mixer] = useState(() => new THREE.AnimationMixer(nodes.mesh))
|
|
|
|
const [mixer] = useState(() => new THREE.AnimationMixer(nodes.mesh))
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
useEffect(() => {
|
|
|
|
api.subscribe(
|
|
|
|
api.subscribe(
|
|
|
|
(state: Transform | null) => {
|
|
|
|
(state: Transform | undefined | null) => {
|
|
|
|
if (!state || !actions.current) {
|
|
|
|
if (!state || !actions.current) {
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -107,7 +111,7 @@ const Human: React.FC<JSX.IntrinsicElements['group'] & { id: number }> = ({
|
|
|
|
previousAction.crossFadeTo(newAction, 0.2, true)
|
|
|
|
previousAction.crossFadeTo(newAction, 0.2, true)
|
|
|
|
currentAnimation.current = state.animation
|
|
|
|
currentAnimation.current = state.animation
|
|
|
|
},
|
|
|
|
},
|
|
|
|
(state) => state.userTransforms[id],
|
|
|
|
(state) => state?.userTransforms?.[id],
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}, [id])
|
|
|
|
}, [id])
|
|
|
|
|
|
|
|
|
|
|
@ -158,8 +162,8 @@ const Human: React.FC<JSX.IntrinsicElements['group'] & { id: number }> = ({
|
|
|
|
<group name="root" rotation={[0, -0.09, 0]}>
|
|
|
|
<group name="root" rotation={[0, -0.09, 0]}>
|
|
|
|
<primitive object={nodes.mixamorigHips} />
|
|
|
|
<primitive object={nodes.mixamorigHips} />
|
|
|
|
<skinnedMesh
|
|
|
|
<skinnedMesh
|
|
|
|
material={material}
|
|
|
|
material={material} //@ts-ignore
|
|
|
|
geometry={nodes.mesh.geometry}
|
|
|
|
geometry={nodes.mesh.geometry} //@ts-ignore
|
|
|
|
skeleton={nodes.mesh.skeleton}
|
|
|
|
skeleton={nodes.mesh.skeleton}
|
|
|
|
></skinnedMesh>
|
|
|
|
></skinnedMesh>
|
|
|
|
</group>
|
|
|
|
</group>
|
|
|
|