whx il y a 11 mois
Parent
commit
ccbfb6996b

BIN
virgo.wzfrontend/src/main/resources/static/.DS_Store


BIN
virgo.wzfrontend/src/main/resources/static/vr/.DS_Store


+ 305 - 0
virgo.wzfrontend/src/main/resources/static/vr/index.html

@@ -0,0 +1,305 @@
+<!DOCTYPE html>
+<html lang="en">
+
+	<head>
+		<meta charset="UTF-8">
+		<meta http-equiv="X-UA-Compatible" content="IE=edge">
+		<meta name="viewport" content="width=device-width, initial-scale=1.0">
+		<title>VR看房</title>
+		<script src="./static/js/three.min.js"></script>
+		<script src="https://johnson2heng.github.io/three.js-demo/lib/js/controls/OrbitControls.js"></script>
+		<script src="./static/js/jquery.min.js"></script>
+	</head>
+	<style>
+		* {
+			padding: 0;
+			margin: 0;
+			overflow: hidden;
+		}
+
+		.top_btn {
+			position: absolute;
+			right: 20px;
+			top: 20px;
+			display: flex;
+		}
+
+		.top_btn .item {
+			display: flex;
+			align-items: center;
+			border-radius: 50%;
+			padding: 10px;
+			background-color: rgba(0, 0, 0, .5);
+			margin-right: 10px;
+			cursor: pointer;
+		}
+
+		.top_btn .item img {
+			width: 25px;
+			height: 25px;
+		}
+
+		#menu {
+			position: absolute;
+			bottom: 0px;
+			color: #fff;
+			background: rgba(0, 0, 0, 0.5);
+			padding: 10px;
+			z-index: 102;
+			width: 100%;
+			display: flex;
+			align-items: center;
+		}
+
+		#menu .menu_item {
+			display: flex;
+		}
+
+		#menu .menu_item span {
+			padding: 4px 14px;
+			display: inline-block;
+			border-radius: 2px;
+			cursor: pointer;
+			display: flex;
+			align-items: center;
+		}
+
+		#menu .menu_item .active {
+			background-color: #409eff;
+		}
+	</style>
+
+	<body>
+		<!-- 顶部右侧按钮 -->
+		<div class="top_btn">
+			<div class="item" id="rotate">
+				<img class="start" src="./static/images/rotate.png" alt="">
+				<img class="stop" style="display: none;" src="./static/images/noRotate.png" alt="">
+			</div>
+			<div class="item" id="fullScreen">
+				<img id="openFullScreen" src="./static/images/fullScreen.png" alt="">
+				<img id="outFullScreen" style="display: none;" src="./static/images/outFullScreen.png" alt="">
+			</div>
+		</div>
+		<div id="menu">
+			<div>位置:</div>
+			<div class="menu_item position">
+				<span id="1" class="active">客餐厅</span>
+				<span id="8">客厅</span>
+			</div>
+		</div>
+	</body>
+	<script>
+		let scene = null; //场景对象
+		let renderer = null; //创建渲染器对象
+		let camera = null; //场景可视相机
+		let controls = null;
+		const texLoader = new THREE.TextureLoader(); //纹理贴图加载器TextureLoader
+		var textureObj = new THREE.Texture(); // 纹理对象
+
+		let sphereMesh = null; //球体对象
+		//创建模型
+		initModel(`./static/images/${$('.position .active').attr('id')}.jpg`);
+		//创建相机
+		initSceneCamera();
+
+		function draw() {
+			//渲染场景
+			initScene();
+			//渲染到dom
+			initRender();
+			//渲染控件
+			initControls();
+			//每帧数操作
+			animate();
+			window.onresize = onWindowResize;
+		}
+
+		function initScene() {
+			// 创建3D场景对象Scene
+			scene = new THREE.Scene();
+			scene.add(sphereMesh);
+		}
+		//创建模型
+		function initModel(images) {
+			texLoader.load(images, function(texture) {
+				//翻转图片
+				texture.wrapS = THREE.RepeatWrapping;
+				texture.repeat.x = -1;
+				//创建一个长方体几何对象sphereGeometry
+				const sphereGeometry = new THREE.SphereBufferGeometry(texture.image.width / 100, 32, 32); //球体
+				// 反转X轴上的几何图形,使所有的面点向内。
+				sphereGeometry.scale(-1, 1, 1);
+				//球体纹理
+				const sphereMaterial = new THREE.MeshBasicMaterial({
+					// color: 0x00ffff,
+					// 设置纹理贴图:Texture对象作为材质map属性的属性值
+					map: texture, //map表示材质的颜色贴图属性
+				});
+				// 两个参数分别为几何体sphereGeometry、材质material
+				sphereMesh = new THREE.Mesh(sphereGeometry, sphereMaterial); //网格模型对象Mesh
+				draw();
+			});
+		}
+
+		// 实例化一个透视投影相机对象
+		function initSceneCamera() {
+			var width = window.innerWidth; //窗口宽度
+			var height = window.innerHeight; //窗口高度
+			//创建相机对象
+			// 30:视场角度, width / height:Canvas画布宽高比, 1:近裁截面, 3000:远裁截面
+			camera = new THREE.PerspectiveCamera(45, width / height, 1, 3000);
+			//相机在Three.js三维坐标系中的位置
+			// 根据需要设置相机位置具体值
+			camera.position.set(24, 0, 0);
+			//相机观察目标指向Threejs 3D空间中某个位置
+			camera.lookAt(new THREE.Vector3(0, 0, 0));
+		}
+
+		//控件
+		function initControls() {
+			controls = new THREE.OrbitControls(camera, renderer.domElement);
+			// 如果使用animate方法时,将此函数删除
+			// controls.addEventListener('change', function (e) {
+			//     // render();
+			//     // console.log(e);
+			// });
+			// 使动画循环使用时阻尼或自转 意思是否有惯性
+			controls.enableDamping = true;
+			//动态阻尼系数 就是鼠标拖拽旋转灵敏度
+			controls.dampingFactor = 1.2;
+			//是否可以缩放
+			controls.enableZoom = true;
+			//是否自动旋转
+			controls.autoRotate = true;
+			//设置相机距离原点的最远距离
+			controls.minDistance = 50;
+			//设置相机距离原点的最远距离
+			controls.maxDistance = 50;
+			//是否开启右键拖拽
+			controls.enablePan = false;
+			//旋转时长
+			controls.autoRotateSpeed = 0.5;
+		}
+
+		function animate() {
+			//更新控制器
+			controls.update();
+			render();
+
+			//相当于每帧数执行
+			requestAnimationFrame(animate);
+		}
+
+		//改变时更新
+		function render() {
+			renderer.render(scene, camera);
+		}
+
+		// 在合适的时机,更新纹理图像或属性
+		function updateTexture() {
+			// 修改纹理对象的属性
+			texture.needsUpdate = true;
+		}
+
+		//渲染dom
+		function initRender() {
+			const width = window.innerWidth; //宽度
+			const height = innerHeight; //高度
+			// 创建渲染器对象
+			renderer = new THREE.WebGLRenderer({
+				antialias: true
+			});
+			renderer.setSize(width, height); //设置渲染区域尺寸
+			renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
+			document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
+			renderer.render(scene, camera);
+		}
+
+		//窗口变动触发的函数
+		function onWindowResize() {
+			camera.aspect = window.innerWidth / window.innerHeight;
+			camera.updateProjectionMatrix();
+			render();
+			renderer.setSize(window.innerWidth, window.innerHeight);
+		}
+
+		//是否旋转
+		$('#rotate img').click(function() {
+			if (controls && controls.autoRotate) {
+				$('#rotate .stop').show();
+				$('#rotate .start').hide();
+				controls.autoRotate = false;
+			} else {
+				controls.autoRotate = true;
+				$('#rotate .start').show();
+				$('#rotate .stop').hide();
+			}
+		})
+		//是否全屏
+		$('#fullScreen').click(function() {
+			if (document.fullscreenElement) {
+				$('#openFullScreen').show();
+				$('#outFullScreen').hide();
+				exitFullscreen()
+			} else {
+				$('#outFullScreen').show();
+				$('#openFullScreen').hide();
+				// 启动全屏!
+				allFullScreen(document.documentElement);
+			}
+		})
+
+		// 启动全屏 整个网页! 
+		function allFullScreen(element) {
+			if (element.requestFullscreen) {
+				element.requestFullscreen();
+			} else if (element.mozRequestFullScreen) {
+				element.mozRequestFullScreen();
+			} else if (element.webkitRequestFullscreen) {
+				element.webkitRequestFullscreen();
+			} else if (element.msRequestFullscreen) {
+				element.msRequestFullscreen();
+			}
+		}
+		//退出全屏模式
+		function exitFullscreen() {
+			if (document.exitFullscreen) {
+				document.exitFullscreen();
+			} else if (document.mozCancelFullScreen) {
+				document.mozCancelFullScreen();
+			} else if (document.webkitExitFullscreen) {
+				document.webkitExitFullscreen();
+			}
+		}
+
+		//切换房间
+		$('.position span').click(function() {
+			$(this).addClass('active').siblings().removeClass('active')
+			let images = `./static/images/${$('.position .active').attr('id')}.jpg`
+			updateTexture(images)
+		})
+
+		// 加载新的纹理图片
+		function updateTexture(images) {
+			var newTexture = new THREE.TextureLoader().load(images,
+				function(texture) {
+					// 纹理加载完成后的逻辑处理
+					console.log('纹理加载完成');
+					newTexture.needsUpdate = true;
+					sphereMesh.material.map = newTexture;
+					// 在这里可以执行你的其他操作
+				},
+				function(xhr) {
+					// 进度回调函数
+					var percentComplete = xhr.loaded / xhr.total * 100;
+					console.log('纹理加载进度:' + percentComplete.toFixed(2) + '%');
+				},
+				function(xhr) {
+					// 错误回调函数
+					console.error('纹理加载错误');
+				});
+		}
+	</script>
+
+</html>

BIN
virgo.wzfrontend/src/main/resources/static/vr/static/images/1.jpg


BIN
virgo.wzfrontend/src/main/resources/static/vr/static/images/2.jpg


BIN
virgo.wzfrontend/src/main/resources/static/vr/static/images/3.jpg


BIN
virgo.wzfrontend/src/main/resources/static/vr/static/images/4.jpg


BIN
virgo.wzfrontend/src/main/resources/static/vr/static/images/5.jpg


BIN
virgo.wzfrontend/src/main/resources/static/vr/static/images/6.jpg


BIN
virgo.wzfrontend/src/main/resources/static/vr/static/images/7.jpg


BIN
virgo.wzfrontend/src/main/resources/static/vr/static/images/8.jpg


BIN
virgo.wzfrontend/src/main/resources/static/vr/static/images/fullScreen.png


BIN
virgo.wzfrontend/src/main/resources/static/vr/static/images/noRotate.png


BIN
virgo.wzfrontend/src/main/resources/static/vr/static/images/outFullScreen.png


BIN
virgo.wzfrontend/src/main/resources/static/vr/static/images/rotate.png


+ 328 - 0
virgo.wzfrontend/src/main/resources/static/vr/static/js/OrbitControls.js

@@ -0,0 +1,328 @@
+/**
+ * @author qiao / https://github.com/qiao
+ * @author mrdoob / http://mrdoob.com
+ * @author alteredq / http://alteredqualia.com/
+ * @author WestLangley / http://github.com/WestLangley
+ * @author erich666 / http://erichaines.com
+ */
+
+// This set of controls performs orbiting, dollying (zooming), and panning.
+// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
+//
+//    Orbit - left mouse / touch: one finger move
+//    Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
+//    Pan - right mouse, or arrow keys / touch: three finger swipe
+
+THREE.OrbitControls = function ( object, domElement ) {
+
+	this.object = object;
+
+	this.domElement = ( domElement !== undefined ) ? domElement : document;
+
+	// Set to false to disable this control
+	this.enabled = true;
+
+	// "target" sets the location of focus, where the object orbits around
+	this.target = new THREE.Vector3();
+
+	// How far you can dolly in and out ( PerspectiveCamera only )
+	this.minDistance = 0;
+	this.maxDistance = Infinity;
+
+	// How far you can zoom in and out ( OrthographicCamera only )
+	this.minZoom = 0;
+	this.maxZoom = Infinity;
+
+	// How far you can orbit vertically, upper and lower limits.
+	// Range is 0 to Math.PI radians.
+	this.minPolarAngle = 0; // radians
+	this.maxPolarAngle = Math.PI; // radians
+
+	// How far you can orbit horizontally, upper and lower limits.
+	// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
+	this.minAzimuthAngle = - Infinity; // radians
+	this.maxAzimuthAngle = Infinity; // radians
+
+	// Set to true to enable damping (inertia)
+	// If damping is enabled, you must call controls.update() in your animation loop
+	this.enableDamping = false;
+	this.dampingFactor = 0.25;
+
+	// This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
+	// Set to false to disable zooming
+	this.enableZoom = true;
+	this.zoomSpeed = 1.0;
+
+	// Set to false to disable rotating
+	this.enableRotate = true;
+	this.rotateSpeed = 1.0;
+
+	// Set to false to disable panning
+	this.enablePan = true;
+	this.keyPanSpeed = 7.0;	// pixels moved per arrow key push
+
+	// Set to true to automatically rotate around the target
+	// If auto-rotate is enabled, you must call controls.update() in your animation loop
+	this.autoRotate = false;
+	this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
+
+	// Set to false to disable use of the keys
+	this.enableKeys = true;
+
+	// The four arrow keys
+	this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
+
+	// Mouse buttons
+	this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };
+
+	// for reset
+	this.target0 = this.target.clone();
+	this.position0 = this.object.position.clone();
+	this.zoom0 = this.object.zoom;
+
+	//
+	// public methods
+	//
+
+	this.getPolarAngle = function () {
+
+		return spherical.phi;
+
+	};
+
+	this.getAzimuthalAngle = function () {
+
+		return spherical.theta;
+
+	};
+
+	this.saveState = function () {
+
+		scope.target0.copy( scope.target );
+		scope.position0.copy( scope.object.position );
+		scope.zoom0 = scope.object.zoom;
+
+	};
+
+	this.reset = function () {
+
+		scope.target.copy( scope.target0 );
+		scope.object.position.copy( scope.position0 );
+		scope.object.zoom = scope.zoom0;
+
+		scope.object.updateProjectionMatrix();
+		scope.dispatchEvent( changeEvent );
+
+		scope.update();
+
+		state = STATE.NONE;
+
+	};
+
+	// this method is exposed, but perhaps it would be better if we can make it private...
+	this.update = function () {
+
+		var offset = new THREE.Vector3();
+
+		// so camera.up is the orbit axis
+		var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );
+		var quatInverse = quat.clone().inverse();
+
+		var lastPosition = new THREE.Vector3();
+		var lastQuaternion = new THREE.Quaternion();
+
+		return function update() {
+
+			var position = scope.object.position;
+
+			offset.copy( position ).sub( scope.target );
+
+			// rotate offset to "y-axis-is-up" space
+			offset.applyQuaternion( quat );
+
+			// angle from z-axis around y-axis
+			spherical.setFromVector3( offset );
+
+			if ( scope.autoRotate && state === STATE.NONE ) {
+
+				rotateLeft( getAutoRotationAngle() );
+
+			}
+
+			spherical.theta += sphericalDelta.theta;
+			spherical.phi += sphericalDelta.phi;
+
+			// restrict theta to be between desired limits
+			spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) );
+
+			// restrict phi to be between desired limits
+			spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );
+
+			spherical.makeSafe();
+
+
+			spherical.radius *= scale;
+
+			// restrict radius to be between desired limits
+			spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );
+
+			// move target to panned location
+			scope.target.add( panOffset );
+
+			offset.setFromSpherical( spherical );
+
+			// rotate offset back to "camera-up-vector-is-up" space
+			offset.applyQuaternion( quatInverse );
+
+			position.copy( scope.target ).add( offset );
+
+			scope.object.lookAt( scope.target );
+
+			if ( scope.enableDamping === true ) {
+
+				sphericalDelta.theta *= ( 1 - scope.dampingFactor );
+				sphericalDelta.phi *= ( 1 - scope.dampingFactor );
+
+			} else {
+
+				sphericalDelta.set( 0, 0, 0 );
+
+			}
+
+			scale = 1;
+			panOffset.set( 0, 0, 0 );
+
+			// update condition is:
+			// min(camera displacement, camera rotation in radians)^2 > EPS
+			// using small-angle approximation cos(x/2) = 1 - x^2 / 8
+
+			if ( zoomChanged ||
+				lastPosition.distanceToSquared( scope.object.position ) > EPS ||
+				8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {
+
+				scope.dispatchEvent( changeEvent );
+
+				lastPosition.copy( scope.object.position );
+				lastQuaternion.copy( scope.object.quaternion );
+				zoomChanged = false;
+
+				return true;
+
+			}
+
+			return false;
+
+		};
+
+	}();
+
+	this.dispose = function () {
+
+		scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false );
+		scope.domElement.removeEventListener( 'mousedown', onMouseDown, false );
+		scope.domElement.removeEventListener( 'wheel', onMouseWheel, false );
+
+		scope.domElement.removeEventListener( 'touchstart', onTouchStart, false );
+		scope.domElement.removeEventListener( 'touchend', onTouchEnd, false );
+		scope.domElement.removeEventListener( 'touchmove', onTouchMove, false );
+
+		document.removeEventListener( 'mousemove', onMouseMove, false );
+		document.removeEventListener( 'mouseup', onMouseUp, false );
+
+		window.removeEventListener( 'keydown', onKeyDown, false );
+
+		//scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
+
+	};
+
+	//
+	// internals
+	//
+
+	var scope = this;
+
+	var changeEvent = { type: 'change' };
+	var startEvent = { type: 'start' };
+	var endEvent = { type: 'end' };
+
+	var STATE = { NONE: - 1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY: 4, TOUCH_PAN: 5 };
+
+	var state = STATE.NONE;
+
+	var EPS = 0.000001;
+
+	// current position in spherical coordinates
+	var spherical = new THREE.Spherical();
+	var sphericalDelta = new THREE.Spherical();
+
+	var scale = 1;
+	var panOffset = new THREE.Vector3();
+	var zoomChanged = false;
+
+	var rotateStart = new THREE.Vector2();
+	var rotateEnd = new THREE.Vector2();
+	var rotateDelta = new THREE.Vector2();
+
+	var panStart = new THREE.Vector2();
+	var panEnd = new THREE.Vector2();
+	var panDelta = new THREE.Vector2();
+
+	var dollyStart = new THREE.Vector2();
+	var dollyEnd = new THREE.Vector2();
+	var dollyDelta = new THREE.Vector2();
+
+	function getAutoRotationAngle() {
+
+		return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
+
+	}
+
+	function getZoomScale() {
+
+		return Math.pow( 0.95, scope.zoomSpeed );
+
+	}
+
+	function rotateLeft( angle ) {
+
+		sphericalDelta.theta -= angle;
+
+	}
+
+	function rotateUp( angle ) {
+
+		sphericalDelta.phi -= angle;
+
+	}
+
+	var panLeft = function () {
+
+		var v = new THREE.Vector3();
+
+		return function panLeft( distance, objectMatrix ) {
+
+			v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix
+			v.multiplyScalar( - distance );
+
+			panOffset.add( v );
+
+		};
+
+	}();
+
+	var panUp = function () {
+
+		var v = new THREE.Vector3();
+
+		return function panUp( distance, objectMatrix ) {
+
+			v.setFromMatrixColumn( objectMatrix, 1 ); // get Y column of objectMatrix
+			v.multiplyScalar( distance );
+
+			panOffset.add( v );
+
+		};
+
+	}();
+
+	// deltaX and deltaY are in pixels; right and down are 

Fichier diff supprimé car celui-ci est trop grand
+ 4 - 0
virgo.wzfrontend/src/main/resources/static/vr/static/js/jquery.min.js


Fichier diff supprimé car celui-ci est trop grand
+ 865 - 0
virgo.wzfrontend/src/main/resources/static/vr/static/js/three.min.js