three车辆自由转弯(vue 极品飞车)
//最近没有时间整理代码,就这样吧
<template>
<div>
<div id="map"></div>
</div>
</template>
<script>
// import * as Three from '../../node_modules/three/build/three.module.js';
import "maptalks/dist/maptalks.css";
import * as maptalks from "maptalks";
import * as Three from "three";
import { ThreeLayer } from "maptalks.three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { PointerLockControls } from "three/examples/jsm/controls/PointerLockControls.js";
import { PCDLoader } from "three/examples/jsm/loaders/PCDLoader";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
export default {
name: "ThreeTest",
data() {
return {
map: null,
threeLayer: null,
mapConfig: {
center: [568318.74296, 4314626.47854],
zoom: 12.364821148501335,
pitch: 71.6000000000002,
bearing: -52.200000000000045,
},
camera: null,
scene: null,
renderer: null,
controls: "",
intersections: null,
objects: [],
clock: "",
moveForward: false,
moveLeft: false,
moveBackward: false,
moveRighta: false,
//----车辆参数----------
car: null, //汽车对象
speed: 0,
rSpeed: 0,
run: false,
acceleration: 0.005, //car 转弯半径大小,越小越转弯越陡
deceleration: 0.02, //car溜车长短,越小溜车越久
// maxSpeed: 2,
// lock: -1,
// isBrake: false,
realRotation: -1.6, // 车辆自身真实的旋转度
dirRotation: 0, // 方向上的旋转
addRotation: 0, // 累计的旋转角度
//--------------
direction: new Three.Vector3(),
velocity: new Three.Vector3(),
prevTime: performance.now(),
};
},
methods: {
init() {
var that = this;
this.map = new maptalks.Map("map", {
center: this.mapConfig.center,
zoom: this.mapConfig.zoom,
seamlessZoom: false,
hitDetect: false, // 是否为此地图上的光标样式启用图层命中检测,请禁用它以提高性能。
zoomControl: false,
scaleControl: false,
overviewControl: false,
attribution: false,
pitch: this.mapConfig.pitch,
bearing: this.mapConfig.bearing,
spatialReference: {
projection: "identity",
},
});
//3D图层
this.threeLayer = new ThreeLayer("car", {
forceRenderOnMoving: true,
forceRenderOnRotating: true,
animation: true,
});
this.threeLayer.setZIndex(10);
this.threeLayer.prepareToDraw = function (gl, scene, camera) {
// this.camera = camera;
that.initScene(); //场景对象
that.initPlane(); //地板
that.initCamera(); //相机
that.initWebGLRenderer(); //渲染器
// this.initAxisHelper(); //辅助坐标
that.render();
// this.createControls(); //控件对象
that.loadPointCloud();
that.Car();
that.initControls(); //相机视角
that.initMobile(); //移动
};
this.threeLayer.addTo(this.map);
},
//鼠标控制移动相机视角*****
initControls() {
let that = this;
that.controls = new PointerLockControls(this.camera, document.body);
// var container = document.getElementById("container");
// container.addEventListener("click", function () {
// that.controls.lock();
// });
this.scene.add(that.controls.getObject());
},
initMobile() {
let that = this;
// console.log(this.controls);
var onKeyDown = function (event) {
switch (event.keyCode) {
case 38: // up
case 87: // w
that.run = true;
break;
case 37: // left
case 65: // a
that.rSpeed = 0.02;
break;
case 40: // down
case 83: // s
that.run = false;
break;
case 39: // right
case 68: // d
that.rSpeed = -0.02;
break;
}
};
var onKeyUp = function (event) {
switch (event.keyCode) {
case 38: // up
case 87: // w
that.run = false;
break;
case 37: // left
case 65: // a
that.rSpeed = 0;
break;
case 40: // down
case 83: // s
that.run = false;
break;
case 39: // right
case 68: // d
that.rSpeed = 0;
break;
}
};
document.addEventListener("keydown", onKeyDown, false);
document.addEventListener("keyup", onKeyUp, false);
},
// 创建场景对象Scene
initScene() {
this.scene = new Three.Scene();
},
// 相机
initCamera() {
// let container = document.getElementById("map");
this.camera = new Three.PerspectiveCamera(
90,
window.innerWidth / window.innerHeight,
0.1,
10000
);
this.camera.speed = {
z: 0,
x: 0,
};
this.camera.position.set(2, 7, 5); //设置相机位置
// this.camera.lookAt(this.camera.position); //设置相机方向(指向的场景对象)
this.camera.add(new Three.PointLight("#fff", 3)); //设置灯光
},
loadPointCloud() {
var that = this;
// instantiate a loader
var loader = new PCDLoader();
// load a resource
loader.load(
// resource URL
"./trunk.pcd",
// called when the resource is loaded
function (mesh) {
console.log(mesh);
// scene.add(mesh);
mesh.scale.set(1.32, 1.32, 5);
// mesh.position.copy(
// that.threeLayer.coordinateToVector3([567403.0, 4315210.0])
// );
that.threeLayer.addMesh(mesh);
},
// called when loading is in progresses
function (xhr) {
// console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
},
// called when loading has errors
function (error) {
console.log("An error happened");
}
);
},
Car() {
var that = this;
var loader = new GLTFLoader();
let url = "./car.glb";
loader.load(url, function (gltf) {
console.log(gltf);
var model = gltf.scene;
model.name = "car";
// model.rotation.x = 0;
// model.rotation.z =0;
model.rotation.y = -1.5; //car自身旋转度
model.scale.set(0.5, 0.5, 0.5);
// 矫正
model.position.z = -15;
model.position.y = 0;
model.position.x = 0;
that.car = model;
that.scene.add(that.car);
});
},
//地板
initPlane() {
var planeGeometry = new Three.PlaneGeometry(1000, 1000);
//平面使用颜色为0xcccccc的基本材质
// var planeMaterial = new Three.MeshBasicMaterial({ color: 0xcccccc });
this.scene.add(new Three.AmbientLight(0xffffff)); //添加灯光显示地板图片
// ground 添加地面
const loader = new Three.TextureLoader();
const groundTexture = loader.load(require('../../public/Cad1.png')); //图片
// const groundTexture = loader.load(
// require("../assets/grasslight-big.jpeg")
// ); //绿色草地
groundTexture.wrapS = groundTexture.wrapT = Three.RepeatWrapping;
// groundTexture.repeat.set(100, 100);
groundTexture.anisotropy = 16;
groundTexture.encoding = Three.sRGBEncoding;
const groundMaterial = new Three.MeshLambertMaterial({
map: groundTexture,
});
var plane = new Three.Mesh(planeGeometry, groundMaterial);
//设置屏幕的位置和旋转角度
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 0;
plane.position.y = 0;
plane.position.z = 0;
//将平面添加场景中
this.scene.add(plane);
},
//创建渲染器对象
initWebGLRenderer() {
var container = document.getElementById("map");
this.renderer = new Three.WebGLRenderer({ antialias: true });
this.renderer.setSize(container.clientWidth, container.clientHeight); //设置渲染区域尺寸
this.renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
container.appendChild(this.renderer.domElement); //body元素中插入canvas对象
},
//辅助三维坐标系AxisHelper
initAxisHelper() {
this.axisHelper = new Three.AxisHelper(1000);
this.scene.add(this.axisHelper);
},
//处理车辆方向键逻辑及算法
runCarTick() {
if (this.run) {
this.speed += this.acceleration;
// if (this.speed > this.maxSpeed) {
// this.speed = this.maxSpeed;
// }
} else {
this.speed -= this.deceleration;
if (this.speed < 0) {
this.speed = 0;
}
}
var speed = -this.speed;
if (speed === 0) {
return;
}
var time = Date.now();
this.dirRotation += this.rSpeed;
this.realRotation += this.rSpeed;
var rotation = this.dirRotation;
var speedX = Math.sin(rotation) * speed;
var speedZ = Math.cos(rotation) * speed;
var tempX = this.car.position.x + speedX;
var tempZ = this.car.position.z + speedZ;
var tempA = -this.car.rotation.y;
this.car.rotation.y = this.realRotation;
this.car.position.z += speedZ;
this.car.position.x += speedX;
this.camera.rotation.y = rotation;
this.camera.position.x = this.car.position.x + Math.sin(rotation) * 20;
this.camera.position.z = this.car.position.z + Math.cos(rotation) * 20;
},
render: function () {
this.runCarTick();
requestAnimationFrame(this.render); //请求再次执行渲染函数render
this.renderer.render(this.scene, this.camera); //执行渲染操作
},
// 创建控件对象
createControls() {
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
//是否开启右键拖拽
// this.controls.enablePan = false;
//设置自动旋转
// this.controls.autoRotate = true;
// 禁止鼠标操作
this.controls.enabled = false;
},
},
mounted() {
this.init();
},
};
</script>
<style scoped>
#map {
height: 800px;
}
</style>
木秀于林,风必摧之;堆高于岸,流必湍之;行高于众,人必非之。
--何木木