Last active
January 20, 2022 05:32
-
-
Save shrirambalaji/b33f0123af0f17e64e66bbb239990cac to your computer and use it in GitHub Desktop.
exampleGltfModel.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useLayoutEffect, useRef, useState } from "react"; | |
import { useGLTF, useAnimations } from "@react-three/drei"; | |
import { useFrame, useThree } from "@react-three/fiber"; | |
import { Quaternion, Vector3 } from "three"; | |
// import { useCompoundBody} from "@react-three/cannon"; | |
import { useStore } from "../store"; | |
const keys = { | |
KeyW: "forward", | |
KeyS: "backward", | |
KeyA: "left", | |
KeyD: "right", | |
Space: "jump", | |
}; | |
const moveFieldByKey = (key) => keys[key]; | |
// temporary data | |
const walkDirection = new Vector3(); | |
const rotateAngle = new Vector3(0, 1, 0); | |
const rotateQuarternion = new Quaternion(); | |
const cameraTarget = new Vector3(); | |
// constants | |
// const runVelocity = 5; | |
const walkVelocity = 2; | |
const compoundStructure = [ | |
{ | |
position: [0, 0, 0], | |
args: [0.5, 0.4, 0.1], | |
}, | |
{ | |
position: [0, 0.25, 0], | |
args: [0.5, 0.4, 0.1], | |
}, | |
{ | |
position: [0, 0.5, 0], | |
args: [0.5, 0.4, 0.1], | |
}, | |
]; | |
export default function Soldier({ pose, ...props }) { | |
const model = useRef(); | |
const { nodes, materials, animations } = useGLTF("/models/Soldier.glb"); | |
const { actions, names } = useAnimations(animations, model); | |
const [index, setIndex] = useState(pose); | |
const [toggleRun, setToggleRun] = useState(false); | |
const runVelocity = useStore((state) => state.runVelocity); | |
const { camera } = useThree(); | |
function switchRunToggle() { | |
setToggleRun(!toggleRun); | |
} | |
function updateCameraTarget(moveX, moveZ) { | |
// move camera | |
} | |
const usePlayerControls = () => { | |
const [movement, setMovement] = useState({ | |
forward: false, | |
backward: false, | |
left: false, | |
right: false, | |
jump: false, | |
}); | |
useEffect(() => { | |
const handleKeyDown = (e) => { | |
setIndex(1); | |
setMovement((m) => { | |
return { ...m, [moveFieldByKey(e.code)]: true }; | |
}); | |
}; | |
const handleKeyUp = (e) => { | |
setIndex(0); | |
setMovement((m) => { | |
return { ...m, [moveFieldByKey(e.code)]: false }; | |
}); | |
setToggleRun(false); | |
}; | |
document.addEventListener("keydown", handleKeyDown); | |
document.addEventListener("keyup", handleKeyUp); | |
return () => { | |
document.removeEventListener("keydown", handleKeyDown); | |
document.removeEventListener("keyup", handleKeyUp); | |
}; | |
}, []); | |
return movement; | |
}; | |
const { forward, backward, left, right, jump } = usePlayerControls(); | |
useLayoutEffect(() => { | |
// Reset and fade in animation after an index has been changed | |
actions[names[index]].reset().fadeIn(0.5).play(); | |
// In the clean-up phase, fade it out | |
return () => actions[names[index]].fadeOut(0.5); | |
// actions[names[index]].play() | |
}, [index, actions, names, pose, toggleRun]); | |
useFrame((state) => { | |
let delta = state.clock.getDelta(); | |
if (names[index] == "Run" || names[index] == "Walk") { | |
// calculate towards camera direction | |
let angleYCameraDirection = Math.atan2( | |
camera.position.x - model.current.position.x, | |
camera.position.z - model.current.position.z | |
); | |
// diagonal movement angle offset | |
let directionOffset = getDirectionOffset(forward, backward, right, left); | |
// // rotate model | |
rotateQuarternion.setFromAxisAngle( | |
rotateAngle, | |
angleYCameraDirection + directionOffset | |
); | |
model.current.quaternion.rotateTowards(rotateQuarternion, 0.2); | |
// // calculate direction | |
camera.getWorldDirection(walkDirection); | |
walkDirection.y = 0; | |
walkDirection.normalize(); | |
walkDirection.applyAxisAngle(rotateAngle, directionOffset); | |
// // run/walk velocity | |
// const velocity = names[index] == "Run" ? runVelocity : walkVelocity; | |
const velocity = runVelocity; | |
// // move model & camera | |
const moveX = walkDirection.x * velocity * delta * 80; | |
const moveZ = walkDirection.z * velocity * delta * 80; | |
model.current.position.x += moveX; | |
model.current.position.z += moveZ; | |
// move camera | |
camera.position.x += moveX; | |
camera.position.z += moveZ; | |
// update camera target | |
cameraTarget.x = model.current.position.x; | |
cameraTarget.y = model.current.position.y + 1; | |
cameraTarget.z = model.current.position.z; | |
state.controls.target = cameraTarget; | |
} | |
}); | |
return ( | |
<group | |
position={[0, -0.45, -10]} | |
castShadow | |
ref={model} | |
{...props} | |
dispose={null} | |
> | |
<group rotation={[-Math.PI / 2, 0, 0]} scale={[0.01, 0.01, 0.01]}> | |
<primitive object={nodes.mixamorigHips} /> | |
<skinnedMesh | |
wireframe | |
geometry={nodes.vanguard_Mesh.geometry} | |
material={materials.VanguardBodyMat} | |
skeleton={nodes.vanguard_Mesh.skeleton} | |
/> | |
<skinnedMesh | |
geometry={nodes.vanguard_visor.geometry} | |
material={materials.Vanguard_VisorMat} | |
skeleton={nodes.vanguard_visor.skeleton} | |
/> | |
</group> | |
</group> | |
); | |
} | |
function getDirectionOffset(w, s, d, a) { | |
let directionOffset = 0; // w | |
if (a) { | |
if (a) { | |
directionOffset = Math.PI / 4; // w+a | |
} else if (d) { | |
directionOffset = -Math.PI / 4; // w+d | |
} | |
} else if (s) { | |
if (a) { | |
directionOffset = Math.PI / 4 + Math.PI / 2; // s+a | |
} else if (d) { | |
directionOffset = -Math.PI / 4 - Math.PI / 2; // s+d | |
} else { | |
directionOffset = Math.PI; // s | |
} | |
} else if (a) { | |
directionOffset = Math.PI / 2; // a | |
} else if (d) { | |
directionOffset = -Math.PI / 2; // d | |
} | |
return directionOffset; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment