Three 之 three.js (webgl)旋转属性函数的简单整理,以及基于此实现绕轴旋转的简单案例

Three 之 three.js (webgl)旋转函数的简单整理,以及实现绕轴旋转的简单案例

目录

Three 之 three.js (webgl)旋转函数的简单整理,以及实现绕轴旋转的简单案例

一、简单介绍

二、案例简单示意图

三、案例旋转的实现原理

四、注意事项

五、该案例的大概实现步骤

六、关键代码


一、简单介绍

Three js 开发的一些知识整理,方便后期遇到类似的问题,能够及时查阅使用。

本节介绍, three.js (webgl)中几个常用旋转函数的整理,并在此基础上实现一个球体从一点旋转到另一点的简单案例,实现方式很多,这里仅供思路提供,如果有不足之处,欢迎指出,或者你有更好的方法,欢迎留言。

Three js 中的几个旋转属性/函数,值得注意的是:

  • 这几个旋转函数都是基于局部旋转的
  • 注意,这里设置的数值是弧度,需要和角度区分开
  • 角度 转 弧度 MathUtils.degToRad(deg)
  • 弧度 转 角度 MathUtils.radToDeg (rad)

1、Mesh 中的 rotation 属性

属性名 说明 属性值类型 使用方法
.rotation 物体的局部旋转,以弧度来表示 弧度 object3D.rotation.x = MathUtils.degToRad(90)

2、rotateOnAxis 在局部空间中绕着该物体的轴来旋转一个物体

注意:axis  最好是单位向量

方法 传参 使用方法
.rotateOnAxis ( axis : Vector3, angle : Float ) object3D.rotateOnAxis(new Vector3(1,0,0),180)

3、rotateX / rotateY / rotateZ 绕局部空间的轴旋转这个物体

方法 传参 传参类型 使用方法
.rotateX ( rad : Float ) 弧度 object3D.rotateX (MathUtils.degToRad(90))
.rotateY ( rad : Float ) 弧度 object3D.rotateY(MathUtils.degToRad(90))
.rotateZ ( rad : Float ) 弧度 object3D.rotateZ (MathUtils.degToRad(90))

二、案例简单示意图

三、案例旋转的实现原理

1、向量 angleTo 计算 A 向量与 B 向量之前的角度

2、向量 cross 计算 A 向量与 B 向量的法向量,作为旋转轴

3、使用上面获得的数据 ,借助 Mesh.rotateOnAxis 实现从 A  点旋转到 B 点

四、注意事项

1、Mesh.rotateOnAxis 是局部旋转,这里一个技巧是,在圆心位置添加一个父物体,把 A 点物体添加到父物体,旋转父物体,从而实现 从 A 点旋转运动到 B 点

 
 

五、该案例的大概实现步骤

该案例基于Threejs    GitHub - mrdoob/three.js: JavaScript 3D Library. 

工程框架创建实现的

1、创建脚本,引入 Three,创建基本的 Three 环境,添加场景,摄像机,光等

 

2、添加进行旋转演示的 3D 物体

3、 计算需要旋转的相关参数,包括旋转角度(顺时针/逆时针角度),旋转轴向量(顺时针/逆时针轴向量)等

4、实现小球顺时针/逆时针一点一点从 A 运动到 B 点,然后在 animation 或者 render 函数中调用即可

5、到这里,就可以在浏览器运行即可 看到运行效果

六、关键代码

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>10TestRotate</title>
</head>
<body>
<script type="importmap">
			{
				"imports": {
					"three": "../../../build/three.module.js"
				}
			}
		</script>

<script type="module">

	import * as THREE from 'three';

	import { OrbitControls } from '../../jsm/controls/OrbitControls.js';
	import Stats from '../../jsm/libs/stats.module.js';

	let scene, camera, renderer, stats;


	var spheremeshT1;
	var spheremeshT2;

	let POSITION_A ;
	let POSITION_B ;
	let POSITION_Center ;
	let T1RotationBasePositionObject;
	let T2RotationBasePositionObject;
	let targetDegreeT1
	let targetDegreeT2
	var degreeT1 = 0
	var degreeT2 = 0
	let T1RotateAixes
	let T2RotateAixes

	init();
	animate();

	function init() {

		// scene
		initScene();

		// camera
		initCamera();


		// light
		initLight();

		// renderer
		initRenderer();

		// OrbitControls
		initOrbitControls();

		stats = new Stats();
		document.body.appendChild( stats.dom );

		// onWindowResize
		window.addEventListener( 'resize', onWindowResize );

		axiesHelper();

		stats = new Stats();
		document.body.appendChild( stats.dom );

		// window.location.href = renderer.domElement.toDataURL( 'image/png' );

		addTestRoateObject();
	}

	function onWindowResize() {

		camera.aspect = window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
		renderer.setSize( window.innerWidth, window.innerHeight );

	}

	function initScene( ) {

		scene = new THREE.Scene();

	}

	function initCamera( ) {

		camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 200 );
		camera.position.set( 0, 0, 25 );

	}

	function initLight( ) {

		const ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
		scene.add( ambientLight );

		const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.6 );
		directionalLight.position.set( - 1, 1, 100 );
		scene.add( directionalLight );

	}

	function initRenderer( ) {

		renderer = new THREE.WebGLRenderer( { antialias: true } );
		renderer.setSize( window.innerWidth, window.innerHeight );
		renderer.setPixelRatio( window.devicePixelRatio );
		renderer.setClearColor( 0xcccccc );
		document.body.appendChild( renderer.domElement );

	}

	function initOrbitControls( ) {

		const controls = new OrbitControls( camera, renderer.domElement );
		controls.minDistance = 5;
		controls.maxDistance = 50;
		controls.enablePan = false; // 移动 禁止

	}

	function animate() {

		requestAnimationFrame( animate );
		stats.update();
		render();


	}

	function axiesHelper( ) {

		var helper = new THREE.AxesHelper( 20 );
		scene.add( helper );

	}

	function render() {

		renderer.render( scene, camera );

		rotateRunDataT1T2();
	}


	function addTestRoateObject(){
		POSITION_A = new THREE.Vector3( 0, 5, 0 );
		POSITION_B = new THREE.Vector3( 5, 0, 0 );
		POSITION_Center = new THREE.Vector3( 0, 0, 0 );

		var geometry = new THREE.SphereGeometry( 5, 30 ); //矩形平面
		var material = new THREE.MeshPhongMaterial( {} );
		var spheremesh1 = new THREE.Mesh( geometry, material );
		spheremesh1.position.set(POSITION_Center.x, POSITION_Center.y, POSITION_Center.z);
		scene.add( spheremesh1 );

		var geometryA = new THREE.SphereGeometry( 1, 30 ); //矩形平面
		var materialA = new THREE.MeshPhongMaterial( {
			color: '#cc0000'
		} );
		var spheremeshA = new THREE.Mesh( geometryA, materialA );
		spheremeshA.position.set( POSITION_A.x, POSITION_A.y, POSITION_A.z );
		scene.add( spheremeshA );
		var geometryB = new THREE.SphereGeometry( 1, 30 ); //矩形平面
		var materialB = new THREE.MeshPhongMaterial( {
			color: '#cc00cc'
		} );
		var spheremeshB = new THREE.Mesh( geometryB, materialB );

		spheremeshB.position.set( POSITION_B.x, POSITION_B.y, POSITION_B.z);
		scene.add( spheremeshB );


		var geometryT1 = new THREE.SphereGeometry( 1, 30 ); //矩形平面
		var materialT1 = new THREE.MeshPhongMaterial( {} );
		spheremeshT1 = new THREE.Mesh( geometryT1, materialT1 );
		spheremeshT1.position.set( POSITION_A.x, POSITION_A.y, POSITION_A.z );

		// 辅助旋转
		T1RotationBasePositionObject = new THREE.Mesh( new THREE.SphereGeometry( 0.1, 6 ),materialT1);
		T1RotationBasePositionObject.position.set(POSITION_Center.x, POSITION_Center.y, POSITION_Center.z );
		T1RotationBasePositionObject.add(spheremeshT1);
		scene.add( T1RotationBasePositionObject );

		var geometryT2 = new THREE.SphereGeometry( 1, 30 ); //矩形平面
		var materialT2 = new THREE.MeshPhongMaterial( {} );
		spheremeshT2 = new THREE.Mesh( geometryT2, materialT2 );
		spheremeshT2.position.set( POSITION_A.x, POSITION_A.y, POSITION_A.z );

		// 辅助旋转
		T2RotationBasePositionObject = new THREE.Mesh( new THREE.SphereGeometry( 0.1, 6 ),materialT2);
		T2RotationBasePositionObject.position.set(POSITION_Center.x, POSITION_Center.y, POSITION_Center.z );
		T2RotationBasePositionObject.add( spheremeshT2 );
		scene.add( T2RotationBasePositionObject );

		rotateTestDataT1T2();

	}

	function rotateTestDataT1T2() {

		const v1T1 = new THREE.Vector3( POSITION_A.x, POSITION_A.y, POSITION_A.z );
		console.log( v1T1.x + ' ' + v1T1.y + ' ' + v1T1.z );
		const v2T1 = new THREE.Vector3( POSITION_B.x, POSITION_B.y, POSITION_B.z );
		console.log( v2T1.x + ' ' + v2T1.y + ' ' + v2T1.z );
		targetDegreeT1 = v1T1.angleTo( v2T1 );
		console.log( 'targetDegreeT1 ' + targetDegreeT1 );
		v1T1.cross( v2T1 );
		console.log( v1T1.x + ' ' + v1T1.y + ' ' + v1T1.z );

		//T1RotationBasePositionObject.rotateOnAxis( v1T1.normalize(),targetDegreeT1 )
		T1RotateAixes = v1T1.normalize();

		const v1T2 = new THREE.Vector3( POSITION_A.x, POSITION_A.y, POSITION_A.z );
		console.log( v1T2.x + ' ' + v1T2.y + ' ' + v1T2.z );
		const v2T2 = new THREE.Vector3( POSITION_B.x, POSITION_B.y, POSITION_B.z );
		console.log( v2T2.x + ' ' + v2T2.y + ' ' + v2T2.z );
		targetDegreeT2 = v2T2.angleTo( v1T2 );
		console.log( 'targetDegreeT2 ' + targetDegreeT2 );
		const nl = v2T2.cross( v1T2 );
		console.log( v1T2.x + ' ' + v1T2.y + ' ' + v1T2.z );
		const modifyDegree = Math.PI * 2 - targetDegreeT2;
		console.log( modifyDegree );

		//T2RotationBasePositionObject.rotateOnAxis( v1T2.normalize(), modifyDegree)
		targetDegreeT2 = modifyDegree;
		T2RotateAixes = v2T2.normalize();

	}

	function rotateRunDataT1T2() {
		if ( degreeT1 < targetDegreeT1 ) {
			degreeT1 += 0.01;
			T1RotationBasePositionObject.rotateOnAxis( T1RotateAixes, 0.01 );
		}

		if ( degreeT2 < targetDegreeT2 ) {
			degreeT2 += 0.01;
			T2RotationBasePositionObject.rotateOnAxis( T2RotateAixes, 0.01 );
		}

	}

</script>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/u014361280/article/details/124346612