three.js BIM可视化练习

这篇博客详细介绍了如何使用Three.js库创建一个基础的3D场景,包括设置相机、场景、渲染器以及添加光照。作者通过加载本地JSON文件解析3D模型,并使用OrbitControls实现相机的交互控制。此外,还利用dat.GUI库创建了GUI交互界面,允许用户自定义漫游速度和高度。博客中还涉及到了纹理、颜色和透明度的处理。
摘要由CSDN通过智能技术生成

 实现效果:

源代码:

<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8">
	<title>My first three.js app</title>
	<!--head中添加script的引用库js文件-->
	<script type="text/javascript" charset="utf-8" src="js\three.js"></script>
	<script type="text/javascript" charset="utf-8" src="js\stats.js"></script>
	<script type="text/javascript" charset="utf-8" src="js\dat.gui.js"></script>
	<script type="text/javascript" charset="utf-8" src="js\OrbitControls.js"></script>
	<script type="text/javascript" charset="utf-8" src="js\jquery-3.4.1.min.js"></script>
	<script type="text/javascript" charset="utf-8" src="js\zxx.color_exchange.js"></script>
</head>

<body>
	<div>
		<input type="file" id="files" style="display: none" onchange="fileImport();">
	</div>
	<!--body中添加主要编译运行的scirpt代码-->
	<script type="text/javascript">
		//全局变量
		var camera;
		var scene;
		var renderer;
		var jsonSource;
		//【主函数】定义函数
		function init() {
			//【】初始化帧数统计
			var stats = initStats();
			//【1】要素-场景、相机、渲染器、轴
			//场景
			scene = new THREE.Scene();
			//相机 
			camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000000);//创建一个透视相机 可视角度45度 浏览器的全屏的宽高 水平视锥 最近1 最远2000
			camera.position.z = 550;//相机的位置z正半轴250
			//渲染器
			renderer = new THREE.WebGLRenderer({ antialias: true, logarithmicDepthBuffer: true });//打开抗锯齿,使用 logarithmicDepthBuffer 缓冲
			renderer.setClearColor(new THREE.Color("rgb(230, 255, 255)"), 1);//背景
			renderer.setPixelRatio(window.devicePixelRatio);//根据设备设置像素比,避免HiDPI设备上绘图模糊
			renderer.setSize(window.innerWidth, window.innerHeight);
			renderer.shadowMapEnabled = true;//打开阴影渲染
			renderer.sortObjects = true;//定义渲染器是否应对对象进行排序默认是true.false:物体的渲染顺序将会由他们添加到场景中的顺序所决定,适合大部分场景。 

			var ambientLight = new THREE.AmbientLight(0x0c0c0c);
			scene.add(ambientLight);

			//【 】输出
			//相机点位
			camera.position.set(-3000, 4000, 3000);
			camera.lookAt(scene.position);
			//添加渲染输出到HTML元素
			document.body.appendChild(renderer.domElement);

			//【】相机控制
			//1.轨道控制器
			var clock = new THREE.Clock();
			var orbitControls = new THREE.OrbitControls(camera, renderer.domElement);
			orbitControls.minDistance = 0.1; //设置滚轮最近
			orbitControls.maxDistance = 10000000; //设置滚轮最远
			orbitControls.autoRotate = false;//自动旋转
			orbitControls.zoomSpeed = 2;
			//【】GUI交互控制
			var controls = new function () {
				this.导入文件 = function () { $("#files").click() };//点击导入按钮,使files触发点击事件,然后完成读取文件的操作
				this.开始漫游 = function () { };
				this.跳起高度 = 200;
				this.MoveSpeed = 500;
				this.无障碍 = true;
				this.结束漫游 = function () { };
				this.使用说明 = function () { alert("使用说明"); };
			};
			//可视化界面GUI对象,添加控制对象的速度属性
			var gui = new dat.GUI();
			gui.add(controls, '使用说明');
			gui.add(controls, '导入文件');
			var folder = gui.addFolder('漫游');
			folder.add(controls, '开始漫游');
			folder.add(controls, '结束漫游');
			folder.add(controls, '跳起高度', 0, 500);
			folder.add(controls, 'MoveSpeed', 0, 1000);
			folder.add(controls, '无障碍');

			renderScene();
			//【函数】引入requestAnimationFrame()方法,让场景动起来
			function renderScene() {
				//帧数显示刷新
				stats.update();
				//相机控制刷新
				//trackballControls.update(clock.getDelta());
				orbitControls.update();
				requestAnimationFrame(renderScene);//动画循环渲染起来
				renderer.render(scene, camera);//渲染
			}
		}

		//【函数】导入文件
		function fileImport() {
			//获取读取我文件的File对象
			var selectedFile = document.getElementById('files').files[0];
			var name = selectedFile.name; //读取选中文件的文件名
			var size = selectedFile.size; //读取选中文件的大小
			console.log("文件名:" + name + "大小:" + size);
			var reader = new FileReader(); //这是核心,读取操作就是由它完成.
			reader.readAsText(selectedFile); //读取文件的内容,也可以读取文件的URL
			reader.onload = function () {
				//当读取完成后回调这个函数,然后此时文件的内容存储到了result中,直接操作即可
				jsonSource = this.result;
				var strJson = JSON.parse(jsonSource);//对象
				for (let i = 0; i < Object.keys(strJson).length; i++) {
					if (Object.keys(strJson)[i] == "models") {
						var obj = strJson[Object.keys(strJson)[i]];//数组
						for (var j = 0; j < obj.length; j++) {
							var geometrys = obj[j].geometrys;
							for (var k = 0; k < geometrys.length; k++) {
								var vertex = geometrys[k].vertex.split("|");
								var face = geometrys[k].face.split("|");
								//geometry
								var geometry = new THREE.Geometry();
								for (m = 0; m < vertex.length; m++) {
									var ss = vertex[m].split(",");
									geometry.vertices.push(new THREE.Vector3(parseFloat(ss[0]), parseFloat(ss[1]), parseFloat(ss[2])));
								};
								for (m = 0; m < face.length; m++) {
									var ss = face[m].split(",");
									geometry.faces.push(new THREE.Face3(parseInt(ss[0]), parseInt(ss[1]), parseInt(ss[2])));
								};

								//color
								var Reds = parseInt(geometrys[k].RGB.red);
								var Greens = parseInt(geometrys[k].RGB.green);
								var Blues = parseInt(geometrys[k].RGB.blue);
								var RGBs = "RGB(" + Reds + "," + Greens + "," + Blues + ")";
								var RGBss = RGBs.colorHex();
								//opacity
								var transparencys = parseFloat((100 - geometrys[k].transparency) / 100);
								//transparent
								var trans = false;
								if (transparencys != 0) { trans = true };
								//material
								var material = new THREE.MeshBasicMaterial({ color: RGBss, opacity: transparencys, transparent: trans, depthTest: true, depthWrite: true });
								//Edges边线
								var cubeEdges = new THREE.EdgesGeometry(geometry, 85);
								var edgesMtl = new THREE.LineBasicMaterial({ color: 000000 });

								var cubeLine = new THREE.LineSegments(cubeEdges, edgesMtl);
								//mesh
								var mesh = new THREE.Mesh(geometry, material);
								mesh.add(cubeLine);
								mesh.geometry.computeBoundingSphere();
								mesh.geometry.computeFaceNormals();
								mesh.geometry.computeVertexNormals();
								mesh.rotation.x = -0.5 * Math.PI;//需要转90度为水平状态
								scene.add(mesh);
							}
						}
					}
				};
			}
		}


		//【函数】初始化帧数统计模块
		function initStats() {
			var stats = new Stats();
			stats.setMode(0); // 0: fps, 1: mss
			// Align top-left
			stats.domElement.style.position = 'absolute';
			stats.domElement.style.left = '0px';
			stats.domElement.style.top = '0px';
			document.body.appendChild(stats.domElement);
			return stats;
		}
		//【函数】监听函数
		function onRisize() {
			camera.aspect = window.innerWidth / window.innerHeight;
			camera.updateProjectionMatrix();//更新项目整体坐标
			renderer.setSize(window.innerWidth, window.innerHeight);//将输出canvas的大小调整为(width, height)并考虑设备像素比
		}
		//调用主函数
		window.onload = init;
		//监听事件
		window.addEventListener('resize', onRisize, false);
	</script>
</body>

</html>

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值