import { AnimationMixer } from 'three'; import { PointerControls } from './PointerControls'; import { CharacterControls } from './CharacterControls'; import * as THREE from 'three'; import * as RAPIER from '@dimforge/rapier3d' class Hero{ constructor(object, data){ this.object = object; this.data = data; this.model = object.scene //console.log(object) } init(gameEngine){ this.gameEngine = gameEngine; //this.gameEngine.orbitControls.object = this.model; //this.gameEngine.orbitControls.target = this.model.position; //this.gameEngine.orbitControls.enabled = false; //this.model.add(gameEngine.camera) gameEngine.camera.position.set(0,17,-30) gameEngine.camera.lookAt(new THREE.Vector3(this.model.position.x, 5, this.model.position.z)) this.heroCamera = new THREE.Object3D() this.model.add(this.heroCamera) this.heroCamera.applyMatrix4(gameEngine.camera.matrix) this.mixer = new AnimationMixer(this.model); gameEngine.mixers.push( this.mixer ); this.animationsMap = {}; this.object.animations.forEach(a=>{ this.animationsMap[a.name] = this.mixer.clipAction(a); }) // this.actionWalk = this.mixer.clipAction( this.object.animations.find(a=>a.name=='walk') ); // this.actionIdle = this.mixer.clipAction( this.object.animations.find(a=>a.name=='idle') ); // this.actionIdle.play(); // this.activeAction = this.actionIdle; this.pointerControls = new PointerControls(gameEngine.camera, this.model, gameEngine.renderer.domElement); gameEngine.hero = this; // Character Collider // const characterCollider = new THREE.Object3D() // characterCollider.position.y = 3 // gameEngine.activeObjects.add(characterCollider) // const colliderShape = new CANNON.Sphere(0.5) // const colliderBody = new CANNON.Body({ mass: 1, material: gameEngine.phy.slipperyMaterial }) // colliderBody.addShape(colliderShape, new CANNON.Vec3(0, 0.5, 0)) // colliderBody.addShape(colliderShape, new CANNON.Vec3(0, -0.5, 0)) // colliderBody.position.set( // characterCollider.position.x, // characterCollider.position.y, // characterCollider.position.z // ) // colliderBody.linearDamping = 0.95 // colliderBody.angularFactor.set(0, 1, 0) // prevents rotation X,Z axis // //colliderBody.sleepSpeedLimit = 1.0; // gameEngine.phy.world.addBody(colliderBody) let po = gameEngine.phy.add(this.model, 'kinematicPositionBased', false, undefined, 'ball', { radius: 0.28}) // let bodyDesc = RAPIER.RigidBodyDesc.kinematicPositionBased().setTranslation( // // characterCollider.position.x, // // characterCollider.position.y, // // characterCollider.position.z // -1, 3, 1 // ) // let rigidBody = gameEngine.phy.world.createRigidBody(bodyDesc); // let dynamicCollider = RAPIER.ColliderDesc.ball(0.28); // gameEngine.phy.world.createCollider(dynamicCollider, rigidBody.handle); this.characterControls = new CharacterControls(this.model, this.mixer, this.animationsMap, gameEngine.orbitControls, gameEngine.camera, 'idle', new RAPIER.Ray( { x: 0, y: 0, z: 0 }, { x: 0, y: -1, z: 0} ), po.rigidBody, this.pointerControls) // this.characterCollider = characterCollider; // this.colliderBody = colliderBody; this.clock = new THREE.Clock() this.delta = 0 // this.inputVelocity = new THREE.Vector3() // this.velocity = new CANNON.Vec3() // this.quat = new THREE.Quaternion() // this.v = new THREE.Vector3() // this.rotation = new THREE.Euler() // this.targetQuaternion = new THREE.Quaternion() // this.distance = 0 // this.canJump = true; // this.contactNormal = new CANNON.Vec3() // this.upAxis = new CANNON.Vec3(0, 1, 0) // colliderBody.addEventListener('collide', function (e) { // const contact = e.contact // if (contact.bi.id == this.colliderBody.id) { // contact.ni.negate(this.contactNormal) // } else { // this.contactNormal.copy(contact.ni) // } // if (this.contactNormal.dot(this.upAxis) > 0.5) { // if (!this.canJump) { // setAction(animationActions[1], true) // } // this.canJump = true // } // }.bind(this)) this.ready = true; } lockControls(){ this.pointerControls.controls.lock(); } // setAction(toAction, loop){ // if (toAction != this.activeAction) { // let lastAction = this.activeAction; // this.activeAction = toAction // lastAction.fadeOut(0.1) // this.activeAction.reset() // this.activeAction.fadeIn(0.1) // this.activeAction.play() // if (!loop) { // this.activeAction.clampWhenFinished = true // this.activeAction.loop = THREE.LoopOnce // } // } // } update(){ //return if (this.gameEngine.renderer.xr.isPresenting) return; if (this.ready) { let pc = this.pointerControls; pc.update(); let dlt = this.clock.getDelta(); this.delta += dlt; if (this.delta > 0.016){ this.characterControls.update(this.gameEngine.phy.world, this.delta, pc) this.gameEngine.phy.step() this.delta = 0; } } return; let { inputVelocity, velocity, quat, v, targetQuaternion, clock, rotation } = this; // let pc = this.pointerControls; // pc.update(); if (this.ready) { if (this.canJump) { //walking this.mixer.update(this.distance / 100) } else { //were in the air this.mixer.update(this.delta) } const p = this.characterCollider.position p.y -= 1 this.model.position.y = this.characterCollider.position.y this.distance = this.model.position.distanceTo(p) // const rotationMatrix = new THREE.Matrix4() // rotationMatrix.lookAt(p, this.model.position, this.model.up) // targetQuaternion.setFromRotationMatrix(rotationMatrix) // if (!this.model.quaternion.equals(targetQuaternion)) { // this.model.quaternion.rotateTowards(targetQuaternion, this.delta * 10) // } if (this.canJump) { inputVelocity.set(0, 0, 0) if (pc.moveForward) { inputVelocity.z = 1 } if (pc.moveBackward) { inputVelocity.z = -1 } if (pc.moveLeft) { //inputVelocity.x = -1 rotation.y+=2*this.delta } if (pc.moveRight) { //inputVelocity.x = 1 rotation.y-=2*this.delta } //let d = this.gameEngine.camera.position.distanceTo(v); inputVelocity.setLength(this.delta * 10) // apply camera rotation to inputVelocity //euler.y = this.gameEngine.camera.rotation.y; quat.setFromEuler(rotation) inputVelocity.applyQuaternion(quat) //this.gameEngine.camera.updateProjectionMatrix() //this.gameEngine.orbitControls.update() // if (this.gameEngine.orbitControls){ //this.gameEngine.orbitControls.target = v//this.model.position; // //this.gameEngine.orbitControls.update() // } //this.gameEngine.camera.rotateOnAxis(v, rotation.y) } if(inputVelocity.x || inputVelocity.z){ this.setAction(this.actionWalk, true) }else{ this.setAction(this.actionIdle, true) } // this.gameEngine.camera.position.lerp(this.characterCollider.position, 1) // this.gameEngine.camera.rotation.y = rotation.y; this.model.position.lerp(this.characterCollider.position, 1) this.model.rotation.y = rotation.y; } velocity.set(inputVelocity.x, inputVelocity.y, inputVelocity.z) this.colliderBody.applyImpulse(velocity) this.delta = Math.min(clock.getDelta(), 0.1) this.gameEngine.phy.world.step(this.delta) //cannonDebugRenderer.update() this.characterCollider.position.set(this.colliderBody.position.x, this.colliderBody.position.y, this.colliderBody.position.z) // boxes.forEach((b, i) => { // boxMeshes[i].position.set(b.position.x, b.position.y, b.position.z) // boxMeshes[i].quaternion.set(b.quaternion.x, b.quaternion.y, b.quaternion.z, b.quaternion.w) // }) this.characterCollider.getWorldPosition(v) //this.gameEngine.cameraPivot.position.lerp(v, 0.1) // if (this.gameEngine.camera.position.distanceTo(v) > 2){ // this.gameEngine.camera.position.set(v.x+1, 3, v.z + 3); // } //this.gameEngine.camera.lookAt(v.x, 3, v.z); //this.gameEngine.camera.rotation.y = this.model.rotation.y; // this.gameEngine.camera.updateMatrix(); // this.model.updateMatrix(); let cam = this.gameEngine.camera; let vv = new THREE.Vector3(), qq = new THREE.Quaternion; this.heroCamera.getWorldPosition(vv) //this.heroCamera.getWorldQuaternion(qq); cam.position.copy(vv) //cam.setRotationFromQuaternion(qq) cam.lookAt(new THREE.Vector3(this.model.position.x, 2.8, this.model.position.z)) //console.log(vv) // cam.matrixAutoUpdate = false; // cam.matrix.multiplyMatrices(this.model.matrix, cam.matrix) // //cam.matrix.decompose(cam.position, cam.quaternion, cam.scale) // //this.gameEngine.camera.updateMatrix(); // cam.matrixAutoUpdate = true; // this.gameEngine.orbitControls.update() } } export { Hero }