Webgl(ThreeJS)在移动端实现室内漫游的解决方案(附工程)

在移动端实现室内漫游,先看效果截图:

 

整体的漫游Demo效果看链接:

技术点:

一、加载模型

采用异步加载glb模型。

function loadModel(name) {

	var modelName = name + '.glb';

	// model
	var model = null;
	new GLTFLoader().setPath('glb/hp/').load(modelName, function (gltf) {

		scene.add(gltf.scene);
		model = gltf.scene;

		//model.position.x = index * 0.5;
		console.log(model.position.x);
		model.scale.x = 0.1;
		model.scale.y = 0.1;
		model.scale.z = 0.1;
		// console.log(gltf);
		console.log(model);
		//获取一个模型的世界坐标之前,需要执行 更新模型的世界矩阵
		//scene.updateMatrixWorld(true);
		//model.updateMatrixWorld();
		// 声明一个三维向量用来保存网格模型的世界坐标
		//var worldPosition = new THREE.Vector3();
		// 获得世界坐标,执行getWorldPosition方法,提取网格模型的世界坐标结果保存到参数worldPosition中
		//model.getWorldPosition(worldPosition)
		//console.log(worldPosition);
		//console.log("00000000000000000000000000000000000000000000000000");

		if (name == 'SM_daohang') { //if (model.name == 'SM_daohang') {
			daohangModel = model;

			daohangModel.visible = false;
		}

		loadIndex++;

		if (loadIndex < modelList.length) {

			updateProgressBar(loadIndex / modelList.length);
			loadModel(modelList[loadIndex]);
		} else {

			hideProgressBar();
			//
			//hideProgressBar();
			// model.children.forEach(mo => {
			// 	console.log(mo.name);

			// 	if (mo.name == 'SM_fangti_01') {

			// 		//console.log("22222");
			// 		//parentObj = mo;
			// 		//mo.visible = false;
			// 	} else if (mo.name.indexOf('shujia') > -1) {

			// 	}
			// });

			readTxt();
		}

	});



}

二、空间中路线规划

通过在场景中打点记录下要漫游的路线,打点的方法如下:

function onMouseDBClick(event) {

	console.log(camera);

	mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
	mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;

	// 通过鼠标点的位置和当前相机的矩阵计算出raycaster
	raycaster.setFromCamera(mouse, camera);

	// 获取raycaster直线和所有模型相交的数组集合
	var intersects = raycaster.intersectObjects(scene.children);

	// console.log(intersects);
	if (intersects.length > 0) {

		//SM_fangti_01
		//if (intersects[0].object.name == 'SM_fangti_01') {

		var index = 0;
		//console.log(intersects[0].object.parent);
		//intersects[0].object.material.color.set(0xff0000);
		var x = intersects[index].point.x;
		var y = intersects[index].point.y;
		var z = intersects[index].point.z;
		//z += 1;//向上抬高

		//endPosition = new THREE.Vector3(x, y, z);;

		console.log(x, y, z);

		pointsList.push(x);
		pointsList.push(y);
		pointsList.push(z);

		//画点
		positions = [];
		positions.push(x, y, z);

		const geometry2 = new THREE.BufferGeometry();
		const colors2 = [];
		colors2.push(1, 0, 0);
		geometry2.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
		geometry2.setAttribute('color', new THREE.Float32BufferAttribute(colors2, 3));
		geometry2.computeBoundingSphere();
		const material2 = new THREE.PointsMaterial({ size: 0.1, vertexColors: true });
		// if (myPoints2) {
		// 	scene.remove(myPoints2);
		// 	myPoints2 = null;
		// }
		var myPoints2 = new THREE.Points(geometry2, material2);
		scene.add(myPoints2);
		//}
	}

}

三、3D场景中画线

画线:通过line2来实现线条的粗细设置

function drawLine2(pointArr) {
	// Line2 ( LineGeometry, LineMaterial )

	let geometry2 = new LineGeometry();
	//var pointArr = [this.model.start.x, this.model.start.y, this.model.start.z, this.model.end.x, this.model.end.y, this.model.end.z]
	geometry2.setPositions(pointArr);

	let material2 = new LineMaterial({
		linewidth: 0.001,
		color: 'blue',
		dashOffset: 15,
		dashScale: 10,
		dashSize: 10,
		gapSize: 20
	});

	material2.resolution.set(window.innerWidth + 100, window.innerHeight + 100);//这句如果不加宽度仍然无效
	line2 = new Line2(geometry2, material2);
	line2.name = "lines";
	scene.add(line2);

	line2.visible = getBookID();
}

function readTxt() {

	positions = [];

	var arr = testPoints.split(',');
	for (var i = 0; i < arr.length; i++) {
		positions.push(arr[i]);
	}

	//drawLineDashed(positions);
	drawLine2(positions);

}

四、自动漫游

采用twenn.js做的漫游动画,只是简单的漫游,很多细节没有做优化

var tween;
var pathIndex = 0;
function cameraRunPath(time) {

	isRun = true;
	bookClick = false;

	var runPosition = runPath[pathIndex];
	tween = new TWEEN.Tween(camera.position)
		.to({ x: runPosition.x, y: runPosition.y, z: runPosition.z }, time) // 目标位置与时间
		.delay(0) // 延迟时间
		.easing(TWEEN.Easing.Exponential.Out)
		.onUpdate(function () {
			//运动过程

			//controls.moveForward(0.01 * speed);
			//console.log("22222", camera.position);
			//camera.position.set(runPosition.x, runPosition.y, runPosition.z);
			camera.lookAt(runPosition.x, runPosition.y, runPosition.z);
		})
		.onComplete(() => {
			//console.log("99999", camera.position);
			pathIndex++;
			if (pathIndex < runPath.length) {
				var time = pathIndex == 1 ? 4000 : 3000;
				cameraRunPath(time);
			} else {
				camera.rotation.set(-3.08, 0.0455, 3.1388);
				bookClick = true;
				isRun = false;
			}
		});
	tween.easing(TWEEN.Easing.Quadratic.InOut);
	tween.start();
}


五、移动端点击事件的响应。

//点击事件

	document.getElementById("nvImg").onclick = function () { resetButtonEvent(); };

	document.getElementById("lineImg").onclick = function () { lineButtonEvent(); };

	document.getElementById("testbook").onclick = function () { bookButtonEvent(); };
	//window.innerWidth / window.innerHeight
	//document.getElementById("testbook").style.left = ;//第一个div的left值
	//document.getElementById("testbook").style.top = window.innerHeight / 2 + "px";//第一个div的top值
	document.getElementById("testbook").style.display = "none";
	// document.getElementById("playDiv").onclick = function () { playButtonEvent(); };
	// document.getElementById("take_partDiv").onclick = function () { take_partButtonEvent(); };
	// document.getElementById("detailDiv").onclick = function () { detailButtonEvent(); };
	// document.getElementById("fireDiv").onclick = function () { fireButtonEvent(); };
	// document.getElementById("hideDiv").onclick = function () { hideButtonEvent(); };

	if (isPhone()) {
		window.addEventListener('touchstart', onMouseClick, false);
		// window.addEventListener('touchstart', onMouseDown, false);
		// window.addEventListener('touchend', onMouseUp, false);
		window.addEventListener('touchmove', onMouseMove, false);
	} else {
		//dblclick
		//window.addEventListener('dblclick', onMouseDBClick, false);
		window.addEventListener('click', onMouseClick, false);
		// window.addEventListener('mousedown', onMouseDown, false);
		// window.addEventListener('mouseup', onMouseUp, false);
		window.addEventListener('mousemove', onMouseMove, false);
	}

六、最后整体的工程文件供学习

webgl(threejs)实现室内漫游-导航功能-应用于移动端-Javascript文档类资源-CSDN下载

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bricke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值