|
@@ -1,8 +1,10 @@
|
|
|
const THREE = require('three');
|
|
|
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader';
|
|
|
import { Octree } from 'three/examples/jsm/math/Octree.js';
|
|
|
-import { onDocumentMouseMove,onWindowResize } from './listener';
|
|
|
+import { Capsule } from 'three/examples/jsm/math/Capsule.js';
|
|
|
|
|
|
+
|
|
|
+const clock = new THREE.Clock();
|
|
|
//1.建立场景
|
|
|
const scene = new THREE.Scene();
|
|
|
scene.background = new THREE.Color(0x88ccff);
|
|
@@ -26,6 +28,7 @@ const container = document.getElementById('container');
|
|
|
container.appendChild(renderer.domElement);
|
|
|
|
|
|
const keyStates = {};
|
|
|
+const STEPS_PER_FRAME = 5; //一帧多少步
|
|
|
|
|
|
document.addEventListener('resize',onWindowResize,false);
|
|
|
document.addEventListener( 'keydown', ( event ) => {
|
|
@@ -41,17 +44,88 @@ document.addEventListener('mouseup',(event) => {
|
|
|
document.removeEventListener('mousemove',onDocumentMouseMove);
|
|
|
})
|
|
|
|
|
|
+//添加游客
|
|
|
+const worldOctree = new Octree();
|
|
|
+
|
|
|
+const playerCollider = new Capsule( new THREE.Vector3( 0, 0.35, 0 ), new THREE.Vector3( 0, 1, 0 ), 0.35 );
|
|
|
+const playerVelocity = new THREE.Vector3();
|
|
|
+const playerDirection = new THREE.Vector3();
|
|
|
+
|
|
|
+function playerCollisions(){
|
|
|
+ const result = worldOctree.capsuleIntersect(playerCollider);
|
|
|
+ if(result){
|
|
|
+ playerCollider.translate(result.normal.multiplyScalar( result.depth ));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function updatePlayer(deltaTime){
|
|
|
+ const deltaPosition = playerVelocity.clone().multiplyScalar(deltaTime);
|
|
|
+ playerCollider.translate(deltaPosition); //向量相加
|
|
|
+ playerCollisions();
|
|
|
+ camera.position.copy(playerCollider.end);
|
|
|
+}
|
|
|
+
|
|
|
+function getForwardVector() {
|
|
|
+
|
|
|
+ camera.getWorldDirection( playerDirection );
|
|
|
+ playerDirection.y = 0;
|
|
|
+ playerDirection.normalize(); //将该向量转换为单位向量
|
|
|
+
|
|
|
+ return playerDirection;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+function getSideVector() {
|
|
|
+
|
|
|
+ camera.getWorldDirection( playerDirection );
|
|
|
+ playerDirection.y = 0;
|
|
|
+ playerDirection.normalize();
|
|
|
+ playerDirection.cross( camera.up );
|
|
|
+
|
|
|
+ return playerDirection;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+function controls( deltaTime ) {
|
|
|
+
|
|
|
+ const speed = 2;
|
|
|
+
|
|
|
+ if ( keyStates[ 'KeyW' ] ) {
|
|
|
+
|
|
|
+ playerVelocity.add( getForwardVector().multiplyScalar( speed * deltaTime ) );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
+ if ( keyStates[ 'KeyS' ] ) {
|
|
|
|
|
|
+ playerVelocity.add( getForwardVector().multiplyScalar( - speed * deltaTime ) );
|
|
|
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( keyStates[ 'KeyA' ] ) {
|
|
|
+
|
|
|
+ playerVelocity.add( getSideVector().multiplyScalar( - speed * deltaTime ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( keyStates[ 'KeyD' ] ) {
|
|
|
+
|
|
|
+ playerVelocity.add( getSideVector().multiplyScalar( speed * deltaTime ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
|
|
|
let loader = new GLTFLoader();
|
|
|
-loader.load('../resource/scene.gltf',function(gltf){
|
|
|
+loader.load('../resource/collision-world.glb',function(gltf){
|
|
|
const model = gltf.scene;
|
|
|
- model.position.set( 1, 1, 0);
|
|
|
- model.scale.set( 0.01, 0.01, 0.01 );
|
|
|
+ // model.position.set( 1, 1, 0);
|
|
|
+ // model.scale.set( 0.1, 0.1, 0.1 );
|
|
|
scene.add(model);
|
|
|
+
|
|
|
+ worldOctree.fromGraphNode( model );
|
|
|
+
|
|
|
animate();
|
|
|
},undefined,function(error){
|
|
|
console.error(error);
|
|
@@ -59,6 +133,27 @@ loader.load('../resource/scene.gltf',function(gltf){
|
|
|
|
|
|
// 5.渲染场景
|
|
|
function animate(){
|
|
|
- requestAnimationFrame( animate );
|
|
|
+ const deltaTime = Math.min( 0.05, clock.getDelta() ) / STEPS_PER_FRAME;
|
|
|
+ for ( let i = 0 ; i < STEPS_PER_FRAME ; i ++ ) {
|
|
|
+
|
|
|
+ controls( deltaTime );
|
|
|
+
|
|
|
+ updatePlayer( deltaTime );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
renderer.render( scene, camera );
|
|
|
+ requestAnimationFrame( animate );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+function onDocumentMouseMove(event){
|
|
|
+ camera.rotation.y -= event.movementX / 500;
|
|
|
+ camera.rotation.x -= event.movementY / 500;
|
|
|
+}
|
|
|
+
|
|
|
+function onWindowResize() {
|
|
|
+ camera.aspect = window.innerWidth / window.innerHeight;
|
|
|
+ camera.updateProjectionMatrix(); //更新摄像机投影矩阵。在任何参数被改变以后必须被调用。
|
|
|
+ renderer.setSize( window.innerWidth, window.innerHeight );
|
|
|
}
|