资源分享
链接: https://pan.baidu.com/s/1o9HtGzEuSxsaKVPRp-RENw
提取码: 2k5y
这个项目是java后台资源服务,启动该项目,前端通过请求获取xodr资源
开源插件,用于渲染xodr,浏览器访问html即可在本地渲染3D效果
自动驾驶场景仿真标准(一)- OpenDRIVE - 知乎
《OpenDRIVE1.6规格文档》3_opendrive1.6 收费站_YMWM_的博客-CSDN博客
/* globals */
var ModuleOpenDrive = null;
var OpenDriveMap = null;
var refline_lines = null;
var road_network_mesh = null;
var roadmarks_mesh = null;
var lane_outline_lines = null;
var roadmark_outline_lines = null;
var ground_grid = null;
var disposable_objs = [];
var mouse = new THREE.Vector2();
var spotlight_info = document.getElementById('spotlight_info');
//相交车道ID
var INTERSECTED_LANE_ID = 0xffffffff;
var INTERSECTED_ROADMARK_ID = 0xffffffff;
//聚集光是否暂停
var spotlight_paused = false;
const COLORS = {
road: 1.0,
roadmark: 1.0,
road_object: 0.9,
lane_outline: 0xae52d4,
roadmark_outline: 0xffffff,
ref_line: 0x69f0ae,
background: 0x444444,
lane_highlight: 0x0000CD,
roadmark_highlight: 0xff0000,
};
//自适应大小
window.addEventListener('resize', onWindowResize, false);
//监听鼠标位置改变
window.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('dblclick', onDocumentMouseDbClick, false);
/* notifactions */
const notyf = new Notyf({
duration: 3000,
position: { x: 'left', y: 'bottom' },
types: [{ type: 'info', background: '#607d8b', icon: false }]
});
//创建渲染器
const renderer = new THREE.WebGLRenderer(
{
antialias: true, //抗锯齿,防失真
sortObjects: false //定义渲染器是否应对对象进行排序
});
//开启投影阴影
renderer.shadowMap.enabled = true;
//设置渲染器渲染区域
renderer.setSize(window.innerWidth, window.innerHeight);
//渲染
document.getElementById('ThreeJS').appendChild(renderer.domElement);
//创建场景
const scene = new THREE.Scene();
//创建透视相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100000);
//让Z轴朝上+
camera.up.set(0, 0, 1); /* Coordinate system with Z pointing up */
//创建控制器
const controls = new THREE.MapControls(camera, renderer.domElement);
controls.addEventListener('start', () => {
/**
* 拖动开始停止开启聚集光和停止旋转
*/
spotlight_paused = true; //聚集光暂停
controls.autoRotate = false; //是否旋转
});
controls.addEventListener('end', () => {
//拖动结束聚集光关闭并且开启旋转
spotlight_paused = false;//聚集光开始
//将其设为true,以自动围绕目标旋转。请注意,如果它被启用,你必须在你的动画循环里调用
// controls.autoRotate = true;//开启旋转
});
controls.autoRotate = true;//开启旋转
//创建平行光
const light = new THREE.DirectionalLight(0xffffff, 1.0);
scene.add(light);
//平行光方向指向原点(0,0,0)
scene.add(light.target);
//添加坐标轴辅助器
const axesHepler = new THREE.AxesHelper(5)
scene.add(axesHepler)
//选择车道线场景
const lane_picking_scene = new THREE.Scene();
//车道线场景背景颜色
lane_picking_scene.background = new THREE.Color(0xffffff);
//路标场景
const roadmark_picking_scene = new THREE.Scene();
//路标场景背景颜色
roadmark_picking_scene.background = new THREE.Color(0xffffff);
//坐标场景
const xyz_scene = new THREE.Scene();
//坐标场景背景颜色
xyz_scene.background = new THREE.Color(0xffffff);
const st_scene = new THREE.Scene();
st_scene.background = new THREE.Color(0xffffff);
//创建渲染器
const lane_picking_texture = new THREE.WebGLRenderTarget(1, 1, { type: THREE.FloatType });
const roadmark_picking_texture = new THREE.WebGLRenderTarget(1, 1, { type: THREE.FloatType });
const xyz_texture = new THREE.WebGLRenderTarget(1, 1, { type: THREE.FloatType });
const st_texture = new THREE.WebGLRenderTarget(1, 1, { type: THREE.FloatType });
//获取顶点着色器
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;
//设置车道中轴线颜色
const refline_material = new THREE.LineBasicMaterial({
//color: COLORS.ref_line,
color: 0x0000FF
});
const road_network_material = new THREE.MeshPhongMaterial({
vertexColors: THREE.VertexColors,
wireframe: PARAMS.wireframe,//显示现况
shininess: 20.0,
transparent: true,
opacity: 0.4
});
//道路线
const lane_outlines_material = new THREE.LineBasicMaterial({
color: COLORS.lane_outline,
//color: 0xCD3278,
});
//外侧线
const roadmark_outlines_material = new THREE.LineBasicMaterial({
color: COLORS.roadmark_outline,
});
const id_material = new THREE.ShaderMaterial({
vertexShader: idVertexShader,
fragmentShader: idFragmentShader,
});
const xyz_material = new THREE.ShaderMaterial({
vertexShader: xyzVertexShader,
fragmentShader: xyzFragmentShader,
});
const st_material = new THREE.ShaderMaterial({
vertexShader: stVertexShader,
fragmentShader: stFragmentShader,
});
const roadmarks_material = new THREE.MeshBasicMaterial({
vertexColors: THREE.VertexColors,
});
const road_objects_material = new THREE.MeshBasicMaterial({
vertexColors: THREE.VertexColors,
side: THREE.DoubleSide,
wireframe: true,
});
/* load WASM + odr map */
libOpenDrive().then(Module => {
console.log(Module)
ModuleOpenDrive = Module;
fetch("http://localhost:8080/upload/factory_v3.1.2.xodr").then((file_data) => {
file_data.text().then((file_text) => {
//加载数据文件
loadFile(file_text, false);
});
});
});
function onFileSelect(file) {
let file_reader = new FileReader();
file_reader.onload = () => { loadFile(file_reader.result, true); };
file_reader.readAsText(file);
}
function loadFile(file_text, clear_map) {
//清除文件系统中保存的文件节点
if (clear_map)
ModuleOpenDrive['FS_unlink']('./data.xodr');
//将文件数据转为节点保存到文件系统本地指定的文件目录,支持读写
ModuleOpenDrive['FS_createDataFile'](".", "data.xodr", file_text, true, true);
//OpenDriveMap不为null,则已经打开过,需要删除地图重新尝试打开
if (OpenDriveMap)
OpenDriveMap.delete()
//打开驱动地图
OpenDriveMap = new ModuleOpenDrive.OpenDriveMap("./data.xodr", PARAMS.lateralProfile, PARAMS.laneHeight, true);
loadOdrMap(clear_map);
}
function reloadOdrMap() {
if (OpenDriveMap)
OpenDriveMap.delete();
OpenDriveMap = new ModuleOpenDrive.OpenDriveMap("./data.xodr", PARAMS.lateralProfile, PARAMS.laneHeight, true);
loadOdrMap(true, false);
}
function loadOdrMap(clear_map = true, fit_view = true) {
//web浏览器内置api,精度微秒级,performance.now是浏览器(Web API)提供的方法,不同浏览器获取到的精度不同。Date.now是Javascript内置方法,差异主要在于浏览器遵循的ECMAScript规范。
const t0 = performance.now();
//是否清除地图
if (clear_map) {
road_network_mesh.userData.odr_road_network_mesh.delete();
scene.remove(road_network_mesh, roadmarks_mesh, road_objects_mesh, refline_lines, lane_outline_lines, roadmark_outline_lines, ground_grid);
lane_picking_scene.remove(...lane_picking_scene.children);
roadmark_picking_scene.remove(...roadmark_picking_scene.children);
xyz_scene.remove(...xyz_scene.children);
st_scene.remove(...st_scene.children);
for (let obj of disposable_objs)
obj.dispose();
}
/**
* 道路中间s方向的线
*/
//获取参考线矩形几何体
const reflines_geom = new THREE.BufferGeometry();
//获取驱动中参考线数据信息
const odr_refline_segments = OpenDriveMap.get_refline_segments(parseFloat(PARAMS.resolution));
//设置参考线坐标点
reflines_geom.setAttribute('position', new THREE.Float32BufferAttribute(getStdVecEntries(odr_refline_segments.vertices).flat(), 3));
//设置参考线坐标点索引
reflines_geom.setIndex(getStdVecEntries(odr_refline_segments.indices, true));
//创建参考线物体
refline_lines = new THREE.LineSegments(reflines_geom, refline_material);
refline_lines.renderOrder = 10;
//设置是否可见
refline_lines.visible = PARAMS.ref_line;
refline_lines.matrixAutoUpdate = false;
disposable_objs.push(reflines_geom);
//将参考线加入场景中
//scene.add(refline_lines);
/*
*道路面
*/
//根据细节级别获取道路网格物体PARAMS.resolution 默认0.3中等级别
const odr_road_network_mesh = OpenDriveMap.get_mesh(parseFloat(PARAMS.resolution));
//获取所有路段的车道(车道id为 -2, -1, 0, 1, 2)
const odr_lanes_mesh = odr_road_network_mesh.lanes_mesh;
//获取所有路段车道点集构建道路物体
const road_network_geom = get_geometry(odr_lanes_mesh);
//设置道路颜色
road_network_geom.attributes.color.array.fill(COLORS.road);
//获取所有路段的车道的起始位置索引
//将索引作为车道开始和结束信息
for (const [vert_start_idx, _] of getStdMapEntries(odr_lanes_mesh.lane_start_indices)) {
// console.log(vert_start_idx)
//根据起始位置索引获取车道信息
const vert_idx_interval = odr_lanes_mesh.get_idx_interval_lane(vert_start_idx);
//console.log(vert_idx_interval)
//结束索引减去起始索引的长度就是该路段该车道的长度
const vert_count = vert_idx_interval[1] - vert_idx_interval[0];
//索引数据压缩
const vert_start_idx_encoded = encodeUInt32(vert_start_idx)
// console.log(vert_start_idx, vert_start_idx_encoded,vert_idx_interval)
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);
}
disposable_objs.push(road_network_geom);
road_network_mesh = new THREE.Mesh(road_network_geom, 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');
scene.add(road_network_mesh);
/**
* 选中被选中的车道进行离屏渲染
*/
const lane_picking_mesh = new THREE.Mesh(road_network_geom, id_material);
lane_picking_mesh.matrixAutoUpdate = false;
lane_picking_scene.add(lane_picking_mesh);
/* xyz coords road network mesh */
const xyz_mesh = new THREE.Mesh(road_network_geom, xyz_material);
xyz_mesh.matrixAutoUpdate = false;
xyz_scene.add(xyz_mesh);
/* st coords road network mesh */
const st_mesh = new THREE.Mesh(road_network_geom, st_material);
st_mesh.matrixAutoUpdate = false;
st_scene.add(st_mesh);
/**
* 车道线宽度区域填充,由于车道线有宽度,宽度区域颜色填充
*/
const odr_roadmarks_mesh = odr_road_network_mesh.roadmarks_mesh;
const roadmarks_geom = get_geometry(odr_roadmarks_mesh);
roadmarks_geom.attributes.color.array.fill(COLORS.roadmark);
for (const [vert_start_idx, _] of 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 = 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);
}
disposable_objs.push(roadmarks_geom);
/* roadmarks mesh */
roadmarks_mesh = new THREE.Mesh(roadmarks_geom, roadmarks_material);
roadmarks_mesh.matrixAutoUpdate = false;
roadmarks_mesh.visible = !(PARAMS.view_mode == 'Outlines') && PARAMS.roadmarks;
scene.add(roadmarks_mesh);
//离屏渲染车道线宽度区域
const roadmark_picking_mesh = new THREE.Mesh(roadmarks_geom, id_material);
roadmark_picking_mesh.matrixAutoUpdate = false;
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 = get_geometry(odr_road_objects_mesh);
road_objects_geom.attributes.color.array.fill(COLORS.road_object);
for (const [vert_start_idx, _] of getStdMapEntries(odr_road_objects_mesh.road_object_start_indices)) {
const vert_idx_interval = odr_roadmarks_mesh.get_idx_interval_roadmark(vert_start_idx);
//console.log(vert_idx_interval)
const vert_count = vert_idx_interval[1] - vert_idx_interval[0];
const vert_start_idx_encoded = 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);
}
disposable_objs.push(road_objects_geom);
/* road objects mesh */
road_objects_mesh = new THREE.Mesh(road_objects_geom, road_objects_material);
road_objects_mesh.matrixAutoUpdate = false;
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(getStdVecEntries(odr_lanes_mesh.get_lane_outline_indices(), true));
lane_outline_lines = new THREE.LineSegments(lane_outlines_geom, lane_outlines_material);
lane_outline_lines.renderOrder = 9;
disposable_objs.push(lane_outlines_geom);
//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(getStdVecEntries(odr_roadmarks_mesh.get_roadmark_outline_indices(), true));
roadmark_outline_lines = new THREE.LineSegments(roadmark_outlines_geom, roadmark_outlines_material);
roadmark_outline_lines.renderOrder = 8;
roadmark_outline_lines.matrixAutoUpdate = false;
disposable_objs.push(roadmark_outlines_geom);
roadmark_outline_lines.visible = PARAMS.roadmarks;
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);
camera.far = max_diag_dist * 1.5;
controls.autoRotate = fit_view;
if (fit_view)
fitViewToBbox(bbox_reflines);
/**
* 网格
*/
let bbox_center_pt = new THREE.Vector3();
bbox_reflines.getCenter(bbox_center_pt);
ground_grid = new THREE.GridHelper(max_diag_dist, max_diag_dist / 10, 0x2f2f2f, 0x2f2f2f);
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);
disposable_objs.push(ground_grid.geometry);
scene.add(ground_grid);
/**
* 灯光
*/
light.position.set(bbox_reflines.min.x, bbox_reflines.min.y, bbox_reflines.max.z + max_diag_dist);
light.target.position.set(bbox_center_pt.x, bbox_center_pt.y, bbox_center_pt.z);
light.position.needsUpdate = true;
light.target.position.needsUpdate = true;
light.target.updateMatrixWorld();
const t1 = performance.now();
console.log("Heap size: " + ModuleOpenDrive.HEAP8.length / 1024 / 1024 + " mb");
//renderer.info.render.triangles简单地显示渲染引擎当前处理的多边形(三角形)数量
const info_msg = `
`;
加载完成
加载用时 ${((t1 - t0) / 1e3).toFixed(2)}s
路段数量 ${OpenDriveMap.roads.size()}
节点数量 ${renderer.info.render.triangles}
notyf.open({ type: 'info', message: info_msg });
//删除数据冗余,避免造成内存泄漏
odr_roadmarks_mesh.delete();
odr_lanes_mesh.delete();
//左上角信息提示
spotlight_info.style.display = "none";
console.log(camera.position)
animate();
}
function animate() {
//控制电脑帧频,防止刷屏过快导致的页面刷3D数据刷新过快 控制每秒30次
setTimeout(function () {
requestAnimationFrame(animate);
}, 1000 / 30);
controls.update();
//spotlight_paused 如果时true怎开始拖动
if (PARAMS.spotlight && !spotlight_paused) {
//camera.setViewOffset(renderer.domElement.width, renderer.domElement.height, mouse.x * window.devicePixelRatio | 0, mouse.y * window.devicePixelRatio | 0, 1, 1);
//改造
camera.setViewOffset(
renderer.domElement.width, //画布的宽度
renderer.domElement.height,//画布的高度
mouse.x | 0, //画布坐标系中,相机的x坐标位置
mouse.y | 0, //画布坐标系中,相机的y坐标位置
1,//副相机的宽度
1 //副相机的高度
);
//离屏渲染
renderer.setRenderTarget(lane_picking_texture);
renderer.render(lane_picking_scene, camera);
renderer.setRenderTarget(roadmark_picking_texture);
renderer.render(roadmark_picking_scene, camera);
renderer.setRenderTarget(xyz_texture);
renderer.render(xyz_scene, camera);
renderer.setRenderTarget(st_texture);
renderer.render(st_scene, camera);
const lane_id_pixel_buffer = new Float32Array(4);
// console.log(mouse)
//拾取颜色
//console.log(mouse.x, window.innerHeight - mouse.y)
renderer.readRenderTargetPixels(
lane_picking_texture,
0, //相机截图左上角为坐标原点,相对于截图左上角而言的渲染起始点x坐标
0,//相机截图左上角为坐标原点,相对于截图左上角而言的渲染起始点y坐标
1, //渲染宽度范围
1, //渲染高度范围
lane_id_pixel_buffer);
const roadmark_id_pixel_buffer = new Float32Array(4);
renderer.readRenderTargetPixels(roadmark_picking_texture, 0, 0, 1, 1, roadmark_id_pixel_buffer);
const xyz_pixel_buffer = new Float32Array(4);
renderer.readRenderTargetPixels(xyz_texture, 0, 0, 1, 1, xyz_pixel_buffer);
xyz_pixel_buffer[0] += OpenDriveMap.x_offs;
xyz_pixel_buffer[1] += OpenDriveMap.y_offs;
const st_pixel_buffer = new Float32Array(4);
renderer.readRenderTargetPixels(st_texture, 0, 0, 1, 1, st_pixel_buffer);
camera.clearViewOffset();
renderer.setRenderTarget(null);
/**
* 选中车道离屏渲染
*/
//选取颜色是否有效,(道路以外的点视为无效)
if (isValid(lane_id_pixel_buffer)) {
//根据颜色值解码成车道ID
const decoded_lane_id = decodeUInt32(lane_id_pixel_buffer);
//自定义数据中获取所有车段中的所有车道数据
const odr_lanes_mesh = road_network_mesh.userData.odr_road_network_mesh.lanes_mesh;
//本次选中的区域车道ID是否和上次一样
if (INTERSECTED_LANE_ID != decoded_lane_id) {
//当前是否是初始化状态,如果不是则进行初始化,防止重复初始化
if (INTERSECTED_LANE_ID != 0xffffffff) {
//根据车道ID索引获取车道信息
const prev_lane_vert_idx_interval = odr_lanes_mesh.get_idx_interval_lane(INTERSECTED_LANE_ID);
road_network_mesh.geometry.attributes.color.array.fill(COLORS.road);
}
//保存选中车道ID
INTERSECTED_LANE_ID = decoded_lane_id;
//根据车道ID获取车道信息
const lane_vert_idx_interval = odr_lanes_mesh.get_idx_interval_lane(INTERSECTED_LANE_ID);
//获取该车道长度
const vert_count = (lane_vert_idx_interval[1] - lane_vert_idx_interval[0]);
//修改离屏渲染场景中该车道的背景颜色
applyVertexColors(road_network_mesh.geometry.attributes.color, new THREE.Color(COLORS.lane_highlight), lane_vert_idx_interval[0], vert_count);
//手动更新颜色值
road_network_mesh.geometry.attributes.color.needsUpdate = true;
//显示左上角信息展示
spotlight_info.style.display = "block";
}
//使用过后删除数据冗余,避免造成内存泄漏
odr_lanes_mesh.delete();
} else {//鼠标拾取无效色素
//恢复初始化数据
//当前是否已经是初始化状态如果不是则进行初始化
if (INTERSECTED_LANE_ID != 0xffffffff) {
console.log("重叠了")
const odr_lanes_mesh = road_network_mesh.userData.odr_road_network_mesh.lanes_mesh;
const lane_vert_idx_interval = odr_lanes_mesh.get_idx_interval_lane(INTERSECTED_LANE_ID);
road_network_mesh.geometry.attributes.color.array.fill(COLORS.road);
road_network_mesh.geometry.attributes.color.needsUpdate = true;
odr_lanes_mesh.delete();
INTERSECTED_LANE_ID = 0xffffffff;
spotlight_info.style.display = "none";
}
}
/**
* 选中车道线-车道线宽度区域离屏渲染
*/
if (isValid(roadmark_id_pixel_buffer)) {
//获取
const decoded_roadmark_id = decodeUInt32(roadmark_id_pixel_buffer);
const odr_roadmarks_mesh = road_network_mesh.userData.odr_road_network_mesh.roadmarks_mesh;
if (INTERSECTED_ROADMARK_ID != decoded_roadmark_id) {
if (INTERSECTED_ROADMARK_ID != 0xffffffff) {
const prev_roadmark_vert_idx_interval = odr_roadmarks_mesh.get_idx_interval_roadmark(INTERSECTED_ROADMARK_ID);
roadmarks_mesh.geometry.attributes.color.array.fill(COLORS.roadmark, prev_roadmark_vert_idx_interval[0] * 3, prev_roadmark_vert_idx_interval[1] * 3);
}
INTERSECTED_ROADMARK_ID = decoded_roadmark_id;
const roadmark_vert_idx_interval = odr_roadmarks_mesh.get_idx_interval_roadmark(INTERSECTED_ROADMARK_ID);
const vert_count = (roadmark_vert_idx_interval[1] - roadmark_vert_idx_interval[0]);
applyVertexColors(roadmarks_mesh.geometry.attributes.color, new THREE.Color(COLORS.roadmark_highlight), roadmark_vert_idx_interval[0], vert_count);
roadmarks_mesh.geometry.attributes.color.needsUpdate = true;
}
odr_roadmarks_mesh.delete();
} else {
if (INTERSECTED_ROADMARK_ID != 0xffffffff) {
const odr_roadmarks_mesh = road_network_mesh.userData.odr_road_network_mesh.roadmarks_mesh;
const roadmark_vert_idx_interval = odr_roadmarks_mesh.get_idx_interval_lane(INTERSECTED_ROADMARK_ID);
roadmarks_mesh.geometry.attributes.color.array.fill(COLORS.roadmark, roadmark_vert_idx_interval[0] * 3, roadmark_vert_idx_interval[1] * 3);
roadmarks_mesh.geometry.attributes.color.needsUpdate = true;
INTERSECTED_ROADMARK_ID = 0xffffffff;
odr_roadmarks_mesh.delete();
}
}
if (INTERSECTED_LANE_ID != 0xffffffff) {
const odr_lanes_mesh = road_network_mesh.userData.odr_road_network_mesh.lanes_mesh;
const road_id = odr_lanes_mesh.get_road_id(INTERSECTED_LANE_ID);
const lanesec_s0 = odr_lanes_mesh.get_lanesec_s0(INTERSECTED_LANE_ID);
const lane_id = odr_lanes_mesh.get_lane_id(INTERSECTED_LANE_ID);
const lane_type = OpenDriveMap.roads.get(road_id).s_to_lanesection.get(lanesec_s0).id_to_lane.get(lane_id).type;
odr_lanes_mesh.delete();
spotlight_info.innerHTML = `
`;
路段编号 ${road_id}
横断面 ${lanesec_s0.toFixed(2)}
车道 ${lane_id} ${lane_type}
s/t [${st_pixel_buffer[0].toFixed(2)}, ${st_pixel_buffer[1].toFixed(2)}]
世界坐标 [${xyz_pixel_buffer[0].toFixed(2)}, ${xyz_pixel_buffer[1].toFixed(2)}, ${xyz_pixel_buffer[2].toFixed(2)}]
}
}
renderer.render(scene, camera);
}
//集合体
function get_geometry(odr_meshunion) {
const geom = new THREE.BufferGeometry();
geom.setAttribute('position', new THREE.Float32BufferAttribute(getStdVecEntries(odr_meshunion.vertices, true).flat(), 3));
//获取uv坐标
geom.setAttribute('st', new THREE.Float32BufferAttribute(getStdVecEntries(odr_meshunion.st_coordinates, true).flat(), 2));
//设置点颜色
geom.setAttribute('color', new THREE.Float32BufferAttribute(new Float32Array(geom.attributes.position.count * 3), 3));
//设置几何体唯一编号
geom.setAttribute('id', new THREE.Float32BufferAttribute(new Float32Array(geom.attributes.position.count * 4), 4));
// geom.setAttribute('ids', new THREE.Float32BufferAttribute(new Float32Array(geom.attributes.position.count * 4), 4));
//设置几何体索引数据
geom.setIndex(getStdVecEntries(odr_meshunion.indices, true));
geom.computeVertexNormals();
return geom;
}
//奇幻照相机视角
function fitViewToBbox(bbox, restrict_zoom = true) {
let center_pt = new THREE.Vector3();
//返回盒子的中心点
bbox.getCenter(center_pt);
const l2xy = 0.5 * Math.sqrt(Math.pow(bbox.max.x - bbox.min.x, 2.0) + Math.pow(bbox.max.y - bbox.min.y, 2));
const fov2r = (camera.fov * 0.5) * (Math.PI / 180.0);
const dz = l2xy / Math.tan(fov2r);
camera.position.set(bbox.min.x, center_pt.y, bbox.max.z + dz);
controls.target.set(center_pt.x, center_pt.y, center_pt.z);
if (restrict_zoom)
controls.maxDistance = center_pt.distanceTo(bbox.max) * 1.2;
controls.update();
}
function fitViewToObj(obj) {
const bbox = new THREE.Box3().setFromObject(obj);
fitViewToBbox(bbox);
}
//改变颜色
function applyVertexColors(buffer_attribute, color, offset, count) {
//buffer_attribute.itemSize颜色宽度
const colors = new Float32Array(count * buffer_attribute.itemSize);
for (let i = 0; i < (count * buffer_attribute.itemSize); i += buffer_attribute.itemSize) {
colors[i] = color.r;
colors[i + 1] = color.g;
colors[i + 2] = color.b;
// colors[i] =0;
// colors[i + 1] = 0;
// colors[i + 2] = 255;
}
//根据颜色偏移设置改变颜色值
buffer_attribute.array.set(colors, offset * buffer_attribute.itemSize);
}
function getStdMapKeys(std_map, delete_map = false) {
let map_keys = [];
const map_keys_vec = std_map.keys();
for (let idx = 0; idx < map_keys_vec.size(); idx++)
map_keys.push(map_keys_vec.get(idx));
map_keys_vec.delete();
if (delete_map)
std_map.delete();
return map_keys;
}
function getStdMapEntries(std_map) {
let map_entries = [];
//key路段索引 , std_map.get(key)车道编号
for (let key of getStdMapKeys(std_map)) {
//console.log(key, std_map.get(key))
map_entries.push([key, std_map.get(key)]);
}
// console.log("总数量", map_entries.length)
return map_entries;
}
function getStdVecEntries(std_vec, delete_vec = false, ArrayType = null) {
//获取道路网格三位坐标点数据
let entries = ArrayType ? new ArrayType(std_vec.size()) : new Array(std_vec.size());
for (let idx = 0; idx < std_vec.size(); idx++)
entries[idx] = std_vec.get(idx);
if (delete_vec)
std_vec.delete();
return entries;
}
//判断当前拾取颜色是否是道路范围的颜色,否则视为无效拾取
function isValid(rgba) {
return !(rgba[0] == 1 && rgba[1] == 1 && rgba[2] == 1 && rgba[3] == 1);
}
//数据压缩
function encodeUInt32(ui32) {
rgba = new Float32Array(4);
rgba[0] = (Math.trunc(ui32) % 256) / 255.;
rgba[1] = (Math.trunc(ui32 / 256) % 256) / 255.;
rgba[2] = (Math.trunc(ui32 / 256 / 256) % 256) / 255.;
rgba[3] = (Math.trunc(ui32 / 256 / 256 / 256) % 256) / 255.;
return rgba;
}
//数据还原
function decodeUInt32(rgba) {
return Math.round(rgba[0] * 255) + Math.round(rgba[1] * 255) * 256 + Math.round(rgba[2] * 255) * 256 * 256 + Math.round(rgba[3] * 255) * 256 * 256 * 256;
}
//监听画面变化,更新渲染画面,(自适应的大小)
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
}
//记录鼠标位置
function onDocumentMouseMove(event) {
event.preventDefault();
console.log()
// let middleX = window.innerWidth / 2
// let middleY = window.innerHeight / 2
// let x = 0
// let y = 0
// x = (event.clientX - middleX) / middleX
// y = (middleY - event.clientY) / middleY
mouse.x = event.clientX;
mouse.y = event.clientY;
}
//双击切换选中视角
function onDocumentMouseDbClick(e) {
//判断是否是初始换状态
if (INTERSECTED_LANE_ID != 0xffffffff) {
console.log("双击")
//获取车道线
const odr_lanes_mesh = road_network_mesh.userData.odr_road_network_mesh.lanes_mesh;
const lane_vert_idx_interval = odr_lanes_mesh.get_idx_interval_lane(INTERSECTED_LANE_ID);
//根据索引获取坐标
const vertA = odr_lanes_mesh.vertices.get(lane_vert_idx_interval[0]);
const vertB = odr_lanes_mesh.vertices.get(lane_vert_idx_interval[1] - 1);
console.log(vertA, vertB)
odr_lanes_mesh.delete();
const bbox = new THREE.Box3();
//flat, 将数组所有元素都降维(一维)
bbox.setFromArray([vertA, vertB].flat());
fitViewToBbox(bbox, false);
}
}
效果图: