import * as THREE from "three";
import {
	OrbitControls
} from "three/examples/jsm/controls/OrbitControls";
import {
	RGBELoader
} from "three/examples/jsm/loaders/RGBELoader";
import {
	Reflector
} from "three/examples/jsm/objects/Reflector";
import {
	GLTFLoader
} from "three/examples/jsm/loaders/GLTFLoader";
import {
	DRACOLoader
} from "three/examples/jsm/loaders/DRACOLoader";
import {
	Line2
} from "three/examples/jsm/lines/Line2";
// import gsap from "gsap";
// import * as CANNON from "cannon-es";

import * as echarts from "echarts";

export let openDriveMixin = {
	data() {
		return {
			ModuleOpenDrive: null,
			OpenDriveMap: null,
			INTERSECTED_LANE_ID: 0xffffffff,
			INTERSECTED_ROADMARK_ID: 0xffffffff,
			refline_material: null,
			lane_outlines_material: null,
			roadmark_outlines_material: null,
			disposable_objs: [],
			id_material: null,
			xyz_material: null,
			st_material: null,
			roadmarks_material: null,
			road_objects_material: null,
			road_network_material: null,
			lane_picking_scene: null,
			roadmark_picking_scene: null,
			xyz_scene: null,
			st_scene: null,
			lane_picking_texture: null,
			roadmark_picking_texture: null,
			xyz_texture: null,
			st_texture: null,
			controls: null,
			ground_grid: null,
			road_network_mesh: null,
			roadmarks_mesh: null,
			road_objects_mesh: null,
			refline_lines: null,
			lane_outline_lines: null,
			roadmark_outline_lines: null,
			COLORS: {
				road: 1.0,
				roadmark: 1.0,
				road_object: 0.9,
				lane_outline: 0x444444,
				roadmark_outline: 0xffffff,
				ref_line: 0x444444,
				background: 0x444444,
				lane_highlight: 0xff3030,
				roadmark_highlight: 0x2F4F4F,
			},
			renderer: null,
			scene: null,
			camera: null,
			light: null,
			lights: [
				-295.65, 117.04, -408.97, -114.11, -272.34, -220.81, 250.93, 194.26,
				338.92, 65.23, -3.58, -16.76,
			],
			startAndEndPoints: {},
			mappingLineId: new Map()
		}
	},
	created() {

	},
	mounted() {
		this.init();
		// this.loadMap("/map/mine4.xodr");
	},
	methods: {
		drawPoint(point) {
			if (this.startAndEndPoints[point.type]) {
				this.scene.remove(this.startAndEndPoints[point.type].target);
			}

			const group = new THREE.Group();
			let cricle = new THREE.CircleBufferGeometry(5, 200);
			let metrial;
			if (point.type == "start") {
				metrial = new THREE.MeshBasicMaterial({
					color: 0x00FF00
				})
			} else {
				metrial = new THREE.MeshBasicMaterial({
					color: 0xff0000
				})
			}
			let mesh = new THREE.Mesh(cricle, metrial);
			group.add(mesh);
			let texture = new THREE.CanvasTexture(this.getTextCanvas(point.name));
			let material = new THREE.SpriteMaterial({
				map: texture
			});
			let sprite = new THREE.Sprite(material);
			sprite.position.set(0, 0, 2);
			group.add(sprite);
			group.position.set(point.x - this.OpenDriveMap.x_offs, point.y - this.OpenDriveMap.y_offs, 0.015);
			this.scene.add(group);
			this.startAndEndPoints[point.type] = {
				target: group,
				point: point
			};
		},
		clearPoint() {
			Object.values(this.startAndEndPoints).forEach(value => {
				this.scene.remove(value.target);
			});
			this.startAndEndPoints = {};
		},
		clearMappingId() {
			this.mappingLineId = new Map();
		},
		loadMap(url) {
			libOpenDrive().then((Module) => {
				this.ModuleOpenDrive = Module;
				fetch(url).then(
					(file_data) => {
						file_data.text().then((file_text) => {
							//加载数据文件
							this.loadFile(file_text, false);
						});
					}
				);
			});
		},
		reloadOdrMap() {
			this.clearPoint();
			if (this.OpenDriveMap) this.OpenDriveMap.delete();
			this.OpenDriveMap = new this.ModuleOpenDrive.OpenDriveMap(
				"./data.xodr",
				PARAMS.lateralProfile,
				PARAMS.laneHeight,
				true
			);
			this.loadOdrMap(true, false);
		},
		reloadNewMap(url) {
			this.clearPoint();
			this.clearMappingId();
			fetch(url, {}).then(response => response.blob()).then(blob => {
				const file = new File([blob], "map.xodr", {
					type: "text/plain",
				});
				this.onFileSelect(file);
			})
		},
		onFileSelect(file) {
			let file_reader = new FileReader();
			file_reader.onload = () => {
				this.loadFile(file_reader.result, true);
			};
			file_reader.readAsText(file);
		},
		loadFile(file_text, clear_map) {
			//清除文件系统中保存的文件节点
			if (clear_map) this.ModuleOpenDrive["FS_unlink"]("./data.xodr");
			//将文件数据转为节点保存到文件系统本地指定的文件目录，支持读写
			this.ModuleOpenDrive["FS_createDataFile"](
				".",
				"data.xodr",
				file_text,
				true,
				true
			);
			//OpenDriveMap不为null，则已经打开过，需要删除地图重新尝试打开
			if (this.OpenDriveMap) this.OpenDriveMap.delete();

			//打开驱动地图
			this.OpenDriveMap = new this.ModuleOpenDrive.OpenDriveMap(
				"./data.xodr",
				PARAMS.lateralProfile,
				PARAMS.laneHeight,
				true
			);
			//this.drawPoint();
			this.loadOdrMap(clear_map);
		},
		loadOdrMap(clear_map = true, fit_view = true) {
			if (clear_map) {
				this.road_network_mesh.userData.odr_road_network_mesh.delete();
				this.scene.remove(
					this.road_network_mesh,
					this.roadmarks_mesh,
					this.road_objects_mesh,
					this.refline_lines,
					this.lane_outline_lines,
					this.roadmark_outline_lines,
					this.ground_grid
				);
				this.lane_picking_scene.remove(...this.lane_picking_scene.children);
				this.roadmark_picking_scene.remove(...this.roadmark_picking_scene.children);
				this.xyz_scene.remove(...this.xyz_scene.children);
				this.st_scene.remove(...this.st_scene.children);
				for (let obj of this.disposable_objs) obj.dispose();
			}
			//web浏览器内置api，精度微秒级，performance.now是浏览器(Web API)提供的方法，不同浏览器获取到的精度不同。Date.now是Javascript内置方法，差异主要在于浏览器遵循的ECMAScript规范。
			const t0 = performance.now();
			//是否清除地图
			/**
			 * 道路中间s方向的线
			 */
			//获取参考线矩形几何体
			const reflines_geom = new THREE.BufferGeometry();
			//获取驱动中参考线数据信息
			const odr_refline_segments = this.OpenDriveMap.get_refline_segments(
				parseFloat(PARAMS.resolution)
			);
			//设置参考线坐标点
			reflines_geom.setAttribute(
				"position",
				new THREE.Float32BufferAttribute(
					this.getStdVecEntries(odr_refline_segments.vertices).flat(),
					3
				)
			);
			//设置参考线坐标点索引
			reflines_geom.setIndex(
				this.getStdVecEntries(odr_refline_segments.indices, true)
			);
			//创建参考线物体
			let refline_lines = new THREE.LineSegments(reflines_geom, this.refline_material);
			this.refline_lines = refline_lines;
			refline_lines.renderOrder = 10;
			//设置是否可见
			refline_lines.visible = PARAMS.ref_line;
			refline_lines.matrixAutoUpdate = false;
			this.disposable_objs.push(reflines_geom);
			//将参考线加入场景中
			this.scene.add(refline_lines);

			/*
			 *道路面
			 */
			//根据细节级别获取道路网格物体PARAMS.resolution 默认0.3中等级别
			const odr_road_network_mesh = this.OpenDriveMap.get_mesh(
				parseFloat(PARAMS.resolution)
			);
			//获取所有路段的车道（车道id为 -2， -1， 0， 1， 2）
			const odr_lanes_mesh = odr_road_network_mesh.lanes_mesh;
			//收集映射
			for (const [vert_start_idx, lineId] of this.getStdMapEntries(odr_lanes_mesh.lane_start_indices)) {
				const road_id = odr_lanes_mesh.get_road_id(vert_start_idx);
				this.mappingLineId.set(road_id + ":" + lineId, vert_start_idx);
			}

			//获取所有路段车道点集构建道路物体
			const road_network_geom = this.get_geometry(odr_lanes_mesh);
			//设置道路颜色
			road_network_geom.attributes.color.array.fill(this.COLORS.road);
			//获取所有路段的车道的起始位置索引
			//将索引作为车道开始和结束信息
			for (const [vert_start_idx, _] of this.getStdMapEntries(odr_lanes_mesh.lane_start_indices)) {
				const vert_idx_interval = odr_lanes_mesh.get_idx_interval_lane(vert_start_idx);
				const vert_count = vert_idx_interval[1] - vert_idx_interval[0];
				const vert_start_idx_encoded = this.encodeUInt32(vert_start_idx);
				const attr_arr = new Float32Array(vert_count * 4);
				for (let i = 0; i < vert_count; i++)
					attr_arr.set(
						vert_start_idx_encoded,
						i * 4
					);
				road_network_geom.attributes.id.array.set(
					attr_arr,
					vert_idx_interval[0] * 4
				);
			}

			this.disposable_objs.push(road_network_geom);
			let road_network_mesh = new THREE.Mesh(
				road_network_geom,
				this.road_network_material
			);
			road_network_mesh.renderOrder = 0;
			road_network_mesh.userData = {
				odr_road_network_mesh
			};
			road_network_mesh.matrixAutoUpdate = false;
			road_network_mesh.visible = !(PARAMS.view_mode == "Outlines");
			this.scene.add(road_network_mesh);
			this.road_network_mesh = road_network_mesh;

			/**
			 * 选中被选中的车道进行离屏渲染
			 */
			const lane_picking_mesh = new THREE.Mesh(road_network_geom, this.id_material);
			lane_picking_mesh.matrixAutoUpdate = false;
			this.lane_picking_scene.add(lane_picking_mesh);

			/* xyz coords road network mesh */
			let xyz_mesh = new THREE.Mesh(road_network_geom, this.xyz_material);
			xyz_mesh.matrixAutoUpdate = false;
			this.xyz_scene.add(xyz_mesh);

			/* st coords road network mesh */
			const st_mesh = new THREE.Mesh(road_network_geom, this.st_material);
			st_mesh.matrixAutoUpdate = false;
			this.st_scene.add(st_mesh);

			/**
			 * 车道线宽度区域填充，由于车道线有宽度，宽度区域颜色填充
			 */
			const odr_roadmarks_mesh = odr_road_network_mesh.roadmarks_mesh;
			const roadmarks_geom = this.get_geometry(odr_roadmarks_mesh);
			roadmarks_geom.attributes.color.array.fill(this.COLORS.roadmark);
			for (const [vert_start_idx, _] of this.getStdMapEntries(odr_roadmarks_mesh
					.roadmark_type_start_indices)) {
				const vert_idx_interval =
					odr_roadmarks_mesh.get_idx_interval_roadmark(vert_start_idx);
				const vert_count = vert_idx_interval[1] - vert_idx_interval[0];
				const vert_start_idx_encoded = this.encodeUInt32(vert_start_idx);
				const attr_arr = new Float32Array(vert_count * 4);
				for (let i = 0; i < vert_count; i++)
					attr_arr.set(
						vert_start_idx_encoded, //数组
						i * 4 //偏移量,每次偏移step：数组大小
					);
				roadmarks_geom.attributes.id.array.set(
					attr_arr,
					vert_idx_interval[0] * 4
				);
			}
			this.disposable_objs.push(roadmarks_geom);

			/* roadmarks mesh */
			let roadmarks_mesh = new THREE.Mesh(roadmarks_geom, this.roadmarks_material);
			this.roadmarks_mesh = roadmarks_mesh;
			roadmarks_mesh.matrixAutoUpdate = false;
			roadmarks_mesh.visible = !(PARAMS.view_mode == "Outlines") && PARAMS.roadmarks;
			this.scene.add(roadmarks_mesh);

			//离屏渲染车道线宽度区域
			const roadmark_picking_mesh = new THREE.Mesh(roadmarks_geom, this.id_material);
			roadmark_picking_mesh.matrixAutoUpdate = false;
			this.roadmark_picking_scene.add(roadmark_picking_mesh);

			/* road objects geometry */
			const odr_road_objects_mesh = odr_road_network_mesh.road_objects_mesh;
			const road_objects_geom = this.get_geometry(odr_road_objects_mesh);
			road_objects_geom.attributes.color.array.fill(this.COLORS.road_object);
			for (const [vert_start_idx, _] of this.getStdMapEntries(
					odr_road_objects_mesh.road_object_start_indices
				)) {
				const vert_idx_interval =
					odr_roadmarks_mesh.get_idx_interval_roadmark(vert_start_idx);
				const vert_count = vert_idx_interval[1] - vert_idx_interval[0];
				const vert_start_idx_encoded = this.encodeUInt32(vert_start_idx);
				const attr_arr = new Float32Array(vert_count * 4);
				for (let i = 0; i < vert_count; i++)
					attr_arr.set(vert_start_idx_encoded, i * 4);
				roadmarks_geom.attributes.id.array.set(
					attr_arr,
					vert_idx_interval[0] * 4
				);
			}
			this.disposable_objs.push(road_objects_geom);

			/* road objects mesh */
			let road_objects_mesh = new THREE.Mesh(
				road_objects_geom,
				this.road_objects_material
			);
			this.road_objects_mesh = road_objects_mesh;
			road_objects_mesh.matrixAutoUpdate = false;
			this.scene.add(road_objects_mesh);

			/**
			 * 车道轮廓线
			 * 道路轮廓线包含车道线，由于每条车道线有宽度，车道轮廓线即为车道线的中心线
			 * id为0的车道轮廓线和参考线s重合
			 */
			const lane_outlines_geom = new THREE.BufferGeometry();
			lane_outlines_geom.setAttribute(
				"position",
				road_network_geom.attributes.position
			);
			lane_outlines_geom.setIndex(
				this.getStdVecEntries(odr_lanes_mesh.get_lane_outline_indices(), true)
			);
			let lane_outline_lines = new THREE.LineSegments(
				lane_outlines_geom,
				this.lane_outlines_material
			);
			this.lane_outline_lines = lane_outline_lines;
			lane_outline_lines.renderOrder = 9;
			this.disposable_objs.push(lane_outlines_geom);
			this.scene.add(lane_outline_lines);

			/**
			 * 道路轮廓线
			 */
			const roadmark_outlines_geom = new THREE.BufferGeometry();
			roadmark_outlines_geom.setAttribute(
				"position",
				roadmarks_geom.attributes.position
			);
			roadmark_outlines_geom.setIndex(
				this.getStdVecEntries(
					odr_roadmarks_mesh.get_roadmark_outline_indices(),
					true
				)
			);
			let roadmark_outline_lines = new THREE.LineSegments(
				roadmark_outlines_geom,
				this.roadmark_outlines_material
			);
			this.roadmark_outline_lines = roadmark_outline_lines;
			roadmark_outline_lines.renderOrder = 8;
			roadmark_outline_lines.matrixAutoUpdate = false;
			this.disposable_objs.push(roadmark_outlines_geom);
			roadmark_outline_lines.visible = PARAMS.roadmarks;
			this.scene.add(roadmark_outline_lines);

			/* fit view and camera */
			const bbox_reflines = new THREE.Box3().setFromObject(refline_lines);
			const max_diag_dist = bbox_reflines.min.distanceTo(bbox_reflines.max);
			this.camera.far = max_diag_dist * 1.5;
			//controls.autoRotate = fit_view;

			this.camera.position.set(0, 0, max_diag_dist / 3);
			// if (fit_view) {
			// 	this.camera.position.set(0, 0, 50);
			// 	// fitViewToBbox(bbox_reflines);
			// 	//fitViewToBbox(bbox_reflines);
			// }

			/**
			 * 网格
			 */
			let bbox_center_pt = new THREE.Vector3();
			bbox_reflines.getCenter(bbox_center_pt);
			let ground_grid = new THREE.GridHelper(
				max_diag_dist * 6,
				max_diag_dist / 10,
				0x2f4f4f,
				0x2f4f4f
			);
			// console.log(THREE.InfiniteGridHelper)
			// let ground_grid = THREE.InfiniteGridHelper(10, 10, new THREE.Color(0x2f4f4f), 500);
			this.ground_grid = ground_grid;
			ground_grid.geometry.rotateX(Math.PI / 2);
			ground_grid.position.set(
				bbox_center_pt.x,
				bbox_center_pt.y,
				bbox_reflines.min.z - 0.1
			);
			this.disposable_objs.push(ground_grid.geometry);
			this.scene.add(ground_grid);

			// const rgbeLoader = new RGBELoader();
			// rgbeLoader.loadAsync("hdr/index8.hdr").then((loader) => {
			// 	loader.needsUpdate = true;
			// 	loader.mapping = THREE.EquirectangularRefractionMapping;
			// 	loader.encoding = THREE.RGBEEncoding; //设置编码属性的值
			// 	loader.mapping = THREE.EquirectangularRefractionMapping;
			// 	loader.minFilter = THREE.NearestFilter; //当一个纹素覆盖小于一个像素时，贴图将如何采样
			// 	loader.magFilter = THREE.NearestFilter; //当一个纹素覆盖大于一个像素时，贴图将如何采样
			// 	loader.flipY = true; //翻转图像的Y轴以匹配WebGL纹理坐标空间
			// 	// this.scene.background = new THREE.Color(0x2F4F4F);
			// 	const sphereGeometry = new THREE.SphereBufferGeometry(max_diag_dist, 100, 100);
			// 	const sphereMetrial = new THREE.MeshBasicMaterial({
			// 		color: 0xffffff,
			// 		map: loader,
			// 	});
			// 	const sphereMesh = new THREE.Mesh(sphereGeometry, sphereMetrial);
			// 	sphereMesh.geometry.scale(1, 1, -1);
			// 	sphereMesh.rotation.x = Math.PI / 2;
			// 	this.scene.add(sphereMesh);
			// });
			// this.scene.environment = new THREE.Color(0x2F4F4F);

			/**
			 * 灯光
			 */
			this.light.position.set(
				bbox_reflines.min.x,
				bbox_reflines.min.y,
				bbox_reflines.max.z + max_diag_dist
			);
			this.light.target.position.set(
				bbox_center_pt.x,
				bbox_center_pt.y,
				bbox_center_pt.z
			);
			this.light.position.needsUpdate = true;
			this.light.target.position.needsUpdate = true;
			this.light.target.updateMatrixWorld();

			// const t1 = performance.now();
			// console.log(
			// 	"Heap size: " + this.ModuleOpenDrive.HEAP8.length / 1024 / 1024 + " mb"
			// );


			//删除数据冗余，避免造成内存泄漏
			odr_roadmarks_mesh.delete();
			odr_lanes_mesh.delete();
			this.animate();
		},
		initThreeJs() {
			// THREE.vertexColors = true;
			//创建渲染器
			this.renderer = new THREE.WebGLRenderer({
				antialias: true, //抗锯齿，防失真
				sortObjects: false, //定义渲染器是否应对对象进行排序
				//对数深度缓冲区,防止模型闪烁
				logarithmicdepthbuffer: true,
			});
			//开启投影阴影
			this.renderer.shadowMap.enabled = true;
			//设置渲染器渲染区域
			this.renderer.setSize(window.innerWidth, window.innerHeight);
			//渲染
			document.getElementById("ThreeJS").appendChild(this.renderer.domElement);
			//创建场景
			this.scene = new THREE.Scene();
			//创建透视相机
			this.camera = new THREE.PerspectiveCamera(
				100,
				window.innerWidth / window.innerHeight,
				0.1,
				100000
			);
			//让Z轴朝上+
			this.camera.up.set(0, 0, 1);

			//创建控制器
			this.controls = new OrbitControls(this.camera, this.renderer.domElement);
			//const controls = new THREE.OrbControls(camera, renderer.domElement);
			// this.controls.addEventListener("start", () => {
			// 	/**
			// 	 * 拖动开始停止开启聚集光和停止旋转
			// 	 */
			// 	spotlight_paused = true; //聚集光暂停
			// 	//controls.autoRotate = false; //是否旋转
			// });
			// this.controls.addEventListener("end", () => {
			// 	//拖动结束聚集光关闭并且开启旋转
			// 	spotlight_paused = false; //聚集光开始
			// 	//将其设为true，以自动围绕目标旋转。请注意，如果它被启用，你必须在你的动画循环里调用
			// 	// controls.autoRotate = true;//开启旋转
			// });
			// controls.autoRotate = true; //开启旋转
			//创建平行光
			this.light;
			for (let index = 0; index < this.lights.length / 2; index++) {
				this.light = new THREE.DirectionalLight(0xffffff, 0.6);
				this.light.position.set(this.lights[2 * index], this.lights[2 * index + 1], 5);
				this.scene.add(this.light);
				//平行光方向指向原点（0，0，0）
				this.scene.add(this.light.target);
			}

			window.addEventListener("resize", this.onWindowResize, false);
		},
		initOffscreen() {
			//选择车道线场景
			this.lane_picking_scene = new THREE.Scene();
			//车道线场景背景颜色
			this.lane_picking_scene.background = new THREE.Color(0xffffff);
			//路标场景
			this.roadmark_picking_scene = new THREE.Scene();
			//路标场景背景颜色
			this.roadmark_picking_scene.background = new THREE.Color(0xffffff);
			//坐标场景
			this.xyz_scene = new THREE.Scene();
			//坐标场景背景颜色
			this.xyz_scene.background = new THREE.Color(0xffffff);
			this.st_scene = new THREE.Scene();
			this.st_scene.background = new THREE.Color(0xffffff);

			//创建渲染器
			this.lane_picking_texture = new THREE.WebGLRenderTarget(1, 1, {
				type: THREE.FloatType,
			});
			this.roadmark_picking_texture = new THREE.WebGLRenderTarget(1, 1, {
				type: THREE.FloatType,
			});
			this.xyz_texture = new THREE.WebGLRenderTarget(1, 1, {
				type: THREE.FloatType,
			});
			this.st_texture = new THREE.WebGLRenderTarget(1, 1, {
				type: THREE.FloatType,
			});

		},
		initMaterial() {
			//获取顶点着色器
			const idVertexShader =
				document.getElementById("idVertexShader").textContent;
			const idFragmentShader =
				document.getElementById("idFragmentShader").textContent;
			const xyzVertexShader =
				document.getElementById("xyzVertexShader").textContent;
			const xyzFragmentShader =
				document.getElementById("xyzFragmentShader").textContent;
			const stVertexShader =
				document.getElementById("stVertexShader").textContent;
			const stFragmentShader =
				document.getElementById("stFragmentShader").textContent;

			//设置车道中轴线颜色
			this.refline_material = new THREE.LineBasicMaterial({
				color: this.COLORS.ref_line,
				//color: 0x0000ff,
			});

			//道路线
			this.lane_outlines_material = new THREE.LineBasicMaterial({
				color: this.COLORS.lane_outline,
			});

			//外侧线
			this.roadmark_outlines_material = new THREE.LineBasicMaterial({
				color: this.COLORS.roadmark_outline,
			});
			this.id_material = new THREE.ShaderMaterial({
				vertexShader: idVertexShader,
				fragmentShader: idFragmentShader,
			});
			this.xyz_material = new THREE.ShaderMaterial({
				vertexShader: xyzVertexShader,
				fragmentShader: xyzFragmentShader,
			});
			this.st_material = new THREE.ShaderMaterial({
				vertexShader: stVertexShader,
				fragmentShader: stFragmentShader,
			});
			this.roadmarks_material = new THREE.MeshBasicMaterial({
				vertexColors: true,
			});
			this.road_objects_material = new THREE.MeshBasicMaterial({
				vertexColors: true,
				side: THREE.DoubleSide,
				wireframe: true,
			});

			this.road_network_material = new THREE.MeshPhongMaterial({
				vertexColors: THREE.VertexColors,
				wireframe: PARAMS.wireframe, //显示现况
				shininess: 20.0,
				transparent: true,
				opacity: 0.4,
			});
		},
		animate() {
			//控制电脑帧频，防止刷屏过快导致的页面刷3D数据刷新过快 控制每秒30次
			setTimeout(() => {
				window.requestAnimationFrame(this.animate);
			}, 1000 / 30);
			this.controls.update();
			this.camera.setViewOffset(
				this.renderer.domElement.width, //画布的宽度
				this.renderer.domElement.height, //画布的高度
				(this.renderer.domElement.width / 2) | 0, //画布坐标系中，相机的x坐标位置
				(this.renderer.domElement.height / 2) | 0, //画布坐标系中，相机的y坐标位置
				1, //副相机的宽度
				1 //副相机的高度
			);
			//离屏渲染
			this.renderer.setRenderTarget(this.lane_picking_texture);
			this.renderer.render(this.lane_picking_scene, this.camera);

			this.renderer.setRenderTarget(this.roadmark_picking_texture);
			this.renderer.render(this.roadmark_picking_scene, this.camera);

			this.renderer.setRenderTarget(this.xyz_texture);
			this.renderer.render(this.xyz_scene, this.camera);

			this.renderer.setRenderTarget(this.st_texture);
			this.renderer.render(this.st_scene, this.camera);

			const lane_id_pixel_buffer = new Float32Array(4);
			this.renderer.readRenderTargetPixels(
				this.lane_picking_texture,
				0,
				0,
				1,
				1,
				this.lane_id_pixel_buffer
			);
			const roadmark_id_pixel_buffer = new Float32Array(4);
			this.renderer.readRenderTargetPixels(
				this.roadmark_picking_texture,
				0,
				0,
				1,
				1,
				this.roadmark_id_pixel_buffer
			);
			const xyz_pixel_buffer = new Float32Array(4);
			this.renderer.readRenderTargetPixels(
				this.xyz_texture,
				0,
				0,
				1,
				1,
				this.xyz_pixel_buffer
			);
			xyz_pixel_buffer[0] += this.OpenDriveMap.x_offs;
			xyz_pixel_buffer[1] += this.OpenDriveMap.y_offs;
			const st_pixel_buffer = new Float32Array(4);
			this.renderer.readRenderTargetPixels(
				this.st_texture,
				0,
				0,
				1,
				1,
				this.st_pixel_buffer
			);

			this.camera.clearViewOffset();
			this.renderer.setRenderTarget(null);

			if (this.isValid(lane_id_pixel_buffer) && false) {
				const decoded_lane_id = this.decodeUInt32(lane_id_pixel_buffer);
				const odr_lanes_mesh =
					this.road_network_mesh.userData.odr_road_network_mesh.lanes_mesh;
				if (this.INTERSECTED_LANE_ID != decoded_lane_id) {
					if (this.INTERSECTED_LANE_ID != 0xffffffff) {
						this.road_network_mesh.geometry.attributes.color.array.fill(
							this.COLORS.road
						);
					}

					this.INTERSECTED_LANE_ID = decoded_lane_id;
					const lane_vert_idx_interval =
						odr_lanes_mesh.get_idx_interval_lane(this.INTERSECTED_LANE_ID);
					const vert_count =
						lane_vert_idx_interval[1] - lane_vert_idx_interval[0];
					this.applyVertexColors(
						this.road_network_mesh.geometry.attributes.color,
						new THREE.Color(this.COLORS.lane_highlight),
						lane_vert_idx_interval[0],
						vert_count
					);
					this.road_network_mesh.geometry.attributes.color.needsUpdate = true;
				}
				odr_lanes_mesh.delete();
			} else {
				if (this.INTERSECTED_LANE_ID != 0xffffffff) {
					const odr_lanes_mesh =
						this.road_network_mesh.userData.odr_road_network_mesh.lanes_mesh;
					const lane_vert_idx_interval =
						odr_lanes_mesh.get_idx_interval_lane(this.INTERSECTED_LANE_ID);
					this.road_network_mesh.geometry.attributes.color.array.fill(this.COLORS.road);
					this.road_network_mesh.geometry.attributes.color.needsUpdate = true;
					odr_lanes_mesh.delete();
					this.INTERSECTED_LANE_ID = 0xffffffff;
				}
			}

			if (this.isValid(roadmark_id_pixel_buffer)) {
				//获取
				const decoded_roadmark_id = this.decodeUInt32(roadmark_id_pixel_buffer);
				const odr_roadmarks_mesh =
					this.road_network_mesh.userData.odr_road_network_mesh.roadmarks_mesh;
				if (this.INTERSECTED_ROADMARK_ID != decoded_roadmark_id) {
					if (this.INTERSECTED_ROADMARK_ID != 0xffffffff) {
						const prev_roadmark_vert_idx_interval =
							odr_roadmarks_mesh.get_idx_interval_roadmark(
								this.INTERSECTED_ROADMARK_ID
							);
						this.roadmarks_mesh.geometry.attributes.color.array.fill(
							this.COLORS.roadmark,
							prev_roadmark_vert_idx_interval[0] * 3,
							prev_roadmark_vert_idx_interval[1] * 3
						);
					}
					this.INTERSECTED_ROADMARK_ID = decoded_roadmark_id;
					const roadmark_vert_idx_interval =
						odr_roadmarks_mesh.get_idx_interval_roadmark(
							this.INTERSECTED_ROADMARK_ID
						);
					const vert_count =
						roadmark_vert_idx_interval[1] - roadmark_vert_idx_interval[0];
					this.applyVertexColors(
						this.roadmarks_mesh.geometry.attributes.color,
						new THREE.Color(this.COLORS.roadmark_highlight),
						roadmark_vert_idx_interval[0],
						vert_count
					);
					this.roadmarks_mesh.geometry.attributes.color.needsUpdate = true;
				}
				odr_roadmarks_mesh.delete();
			} else {
				if (this.INTERSECTED_ROADMARK_ID != 0xffffffff) {
					const odr_roadmarks_mesh =
						this.road_network_mesh.userData.odr_road_network_mesh.roadmarks_mesh;
					const roadmark_vert_idx_interval =
						odr_roadmarks_mesh.get_idx_interval_lane(this.INTERSECTED_ROADMARK_ID);
					this.roadmarks_mesh.geometry.attributes.color.array.fill(
						this.COLORS.roadmark,
						roadmark_vert_idx_interval[0] * 3,
						roadmark_vert_idx_interval[1] * 3
					);
					this.roadmarks_mesh.geometry.attributes.color.needsUpdate = true;
					this.INTERSECTED_ROADMARK_ID = 0xffffffff;
					odr_roadmarks_mesh.delete();
				}
			}

			if (this.INTERSECTED_LANE_ID != 0xffffffff) {
				const odr_lanes_mesh =
					this.road_network_mesh.userData.odr_road_network_mesh.lanes_mesh;
				const road_id = odr_lanes_mesh.get_road_id(this.INTERSECTED_LANE_ID);
				const lanesec_s0 = odr_lanes_mesh.get_lanesec_s0(this.INTERSECTED_LANE_ID);
				const lane_id = odr_lanes_mesh.get_lane_id(this.INTERSECTED_LANE_ID);
				const lane_type = this.OpenDriveMap.roads
					.get(road_id)
					.s_to_lanesection.get(lanesec_s0)
					.id_to_lane.get(lane_id).type;
				odr_lanes_mesh.delete();
			}
			this.renderer.render(this.scene, this.camera);
		},
		fillColorLine(roadId, lineId) {
			lineId = this.mappingLineId.get(roadId + ":" + lineId);
			const odr_lanes_mesh = this.road_network_mesh.userData.odr_road_network_mesh.lanes_mesh;
			const lane_vert_idx_interval = odr_lanes_mesh.get_idx_interval_lane(lineId);
			const vert_count = (lane_vert_idx_interval[1] - lane_vert_idx_interval[0]);
			this.applyVertexColors(this.road_network_mesh.geometry.attributes.color, new THREE.Color(this.COLORS
					.lane_highlight),
				lane_vert_idx_interval[0], vert_count);
			this.road_network_mesh.geometry.attributes.color.needsUpdate = true;
			odr_lanes_mesh.delete();
		},
		clearColorLine(roadId, lineId) {
			lineId = this.mappingLineId.get(roadId + ":" + lineId);
			const odr_lanes_mesh = this.road_network_mesh.userData.odr_road_network_mesh.lanes_mesh;
			const lane_vert_idx_interval = odr_lanes_mesh.get_idx_interval_lane(lineId);
			const vert_count = (lane_vert_idx_interval[1] - lane_vert_idx_interval[0]);
			this.road_network_mesh.geometry.attributes.color.array.fill(
				this.COLORS.road
			);
			this.road_network_mesh.geometry.attributes.color.needsUpdate = true;
			odr_lanes_mesh.delete();
		},
		onWindowResize() {
			this.camera.aspect = window.innerWidth / window.innerHeight;
			this.camera.updateProjectionMatrix();
			this.renderer.setSize(window.innerWidth, window.innerHeight);
			this.renderer.setPixelRatio(window.devicePixelRatio);
		},
		init() {
			this.initThreeJs();
			this.initOffscreen();
			this.initMaterial();
		}
	}
}