new CCDIKSolver( OOI.kira, iks ); // 创建逆运动学求解器

demo案例

new CCDIKSolver(OOI.kira, iks); 在使用某个特定的库或框架来创建一个逆运动学(Inverse Kinematics, IK)求解器实例。逆运动学在机器人学、动画和计算机图形学等领域中非常重要,它用于根据期望的末端执行器(如机器人的手或动画角色的脚)的位置和方向来求解关节的角度。

不过,由于 CCDIKSolverOOI.kiraiks 都不是标准库或广泛认可的API的一部分,我将基于一般的逆运动学求解器和您提供的代码片段来解释。

入参 (Parameters)

  1. OOI.kira

    • 代表机器人或动画角色的对象OOI,而 kira 这个对象包含有关机器人或角色的关节结构、关节限制等信息。
  2. iks

    • 这个参数的具体含义取决于 CCDIKSolver 的设计。但一般来说,它可能包含有关逆运动学问题的信息,如末端执行器的目标位置、方向或其他约束条件。

出参 (Return Value)

  • 代码片段 new CCDIKSolver(OOI.kira, iks); 创建了一个新的 CCDIKSolver 实例,并返回该实例的引用。这个实例可以用来求解逆运动学问题,即给定末端执行器的目标位置和约束条件,计算出关节的角度。

方法 (Methods)

  • 由于 CCDIKSolver 不是标准库的一部分,具体的方法将取决于该类的设计。但一般来说,你可能会看到以下类型的方法:
    • solve():用于求解逆运动学问题,并返回关节角度的解。
    • updateTarget():用于更新末端执行器的目标位置或方向。
    • getJointAngles():用于获取求解得到的关节角度。

属性 (Properties)

  • 类似地,具体的属性将取决于 CCDIKSolver 类的设计。但以下是一些常见的属性:
    • targetPosition:代表末端执行器的目标位置。
    • targetOrientation:代表末端执行器的目标方向。
    • jointAngles:存储求解得到的关节角度。
    • status:表示求解器的状态(如"正在求解"、"已解决"或"无解"等)。
    • ...:其他可能的属性,如关节限制、错误信息等。
html 复制代码
<!DOCTYPE html>
<html lang="en">
	<head>
		<title>three.js webgl - animation - skinning - ik</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<meta name="author" content="Antoine BERNIER (abernier)" />
		<link type="text/css" rel="stylesheet" href="main.css">
		<style>
		body {color:white;}
		#info a {
			color:#4d6675;
		}
		</style>
	</head>
	<body>
		<div id="info">
			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl - inverse kinematics<br />
			Character model by <a href="https://assetstore.unity.com/packages/3d/characters/humanoids/humans/kira-lowpoly-character-100303" target="_blank" rel="noopener">Aki</a>, furnitures from <a href="https://poly.pizza" target="_blank" rel="noopener">poly.pizza</a>, scene by <a href="https://abernier.name/three.js/examples/webgl_esher.html" target="_blank" rel="noopener">abernier</a>. CC0.
		</div>

		<script type="importmap">
		{
			"imports": {
				"three": "../build/three.module.js",
				"three/addons/": "./jsm/"
			}
		}
		</script>

		<script type="module">
		// 导入所需的模块
		import * as THREE from 'three';

		import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
		import { TransformControls } from 'three/addons/controls/TransformControls.js';
		import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
		import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
		import { CCDIKSolver, CCDIKHelper } from './jsm/animation/CCDIKSolver.js';
		import Stats from 'three/addons/libs/stats.module.js';
		import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

		let scene, camera, renderer, orbitControls, transformControls;
		let mirrorSphereCamera;

		const OOI = {};
		let IKSolver;

		let stats, gui, conf;
		const v0 = new THREE.Vector3();

		// 初始化函数
		init().then( animate );

		async function init() {
			// 配置参数
			conf = {
				followSphere: false,
				turnHead: true,
				ik_solver: true,
				update: updateIK
			};

			scene = new THREE.Scene(); // 创建场景
			scene.fog = new THREE.FogExp2( 0xffffff, .17 ); // 添加雾效
			scene.background = new THREE.Color( 0xffffff ); // 设置背景色

			camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.001, 5000 ); // 创建透视相机
			camera.position.set( 0.9728517749133652, 1.1044765132727201, 0.7316689528482836 ); // 设置相机位置
			camera.lookAt( scene.position ); // 设置相机朝向

			const ambientLight = new THREE.AmbientLight( 0xffffff, 8 ); // 创建环境光
			scene.add( ambientLight ); // 将环境光添加到场景中

			renderer = new THREE.WebGLRenderer( { antialias: true, logarithmicDepthBuffer: true } ); // 创建WebGL渲染器
			renderer.setPixelRatio( window.devicePixelRatio ); // 设置像素比例
			renderer.setSize( window.innerWidth, window.innerHeight ); // 设置渲染器尺寸
			document.body.appendChild( renderer.domElement ); // 将渲染器元素添加到body中

			stats = new Stats(); // 创建性能统计对象
			document.body.appendChild( stats.dom ); // 将性能统计元素添加到body中

			orbitControls = new OrbitControls( camera, renderer.domElement ); // 创建轨道控制器
			orbitControls.minDistance = 0.2; // 设置轨道控制器最小距离
			orbitControls.maxDistance = 1.5; // 设置轨道控制器最大距离
			orbitControls.enableDamping = true; // 启用阻尼效果

			const dracoLoader = new DRACOLoader(); // 创建DRACO加载器
			dracoLoader.setDecoderPath( 'jsm/libs/draco/' ); // 设置DRACO解码器路径
			const gltfLoader = new GLTFLoader(); // 创建GLTF加载器
			gltfLoader.setDRACOLoader( dracoLoader ); // 设置GLTF加载器的DRACO加载器

			const gltf = await gltfLoader.loadAsync( 'models/gltf/kira.glb' ); // 异步加载GLTF模型
			gltf.scene.traverse( n => {
				// 遍历模型场景
				if ( n.name === 'head' ) OOI.head = n;
				if ( n.name === 'lowerarm_l' ) OOI.lowerarm_l = n;
				if ( n.name === 'Upperarm_l' ) OOI.Upperarm_l = n;
				if ( n.name === 'hand_l' ) OOI.hand_l = n;
				if ( n.name === 'target_hand_l' ) OOI.target_hand_l = n;

				if ( n.name === 'boule' ) OOI.sphere = n;
				if ( n.name === 'Kira_Shirt_left' ) OOI.kira = n;

			} );
			scene.add( gltf.scene ); // 将GLTF场景添加到场景中

			orbitControls.target.copy( OOI.sphere.position ); // 轨道控制器以球体为焦点
			OOI.hand_l.attach( OOI.sphere ); // 将手臂附加到球体上

			// 创建镜像球体相机
			const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 1024 );
			mirrorSphereCamera = new THREE.CubeCamera( 0.05, 50, cubeRenderTarget );
			scene.add( mirrorSphereCamera );
			const mirrorSphereMaterial = new THREE.MeshBasicMaterial( { envMap: cubeRenderTarget.texture } );
			OOI.sphere.material = mirrorSphereMaterial;

			transformControls = new TransformControls( camera,

 renderer.domElement ); // 创建变换控制器
			transformControls.size = 0.75; // 设置控制器大小
			transformControls.showX = false; // 隐藏X轴
			transformControls.space = 'world'; // 设置变换空间
			transformControls.attach( OOI.target_hand_l ); // 将控制器附加到目标手臂上
			scene.add( transformControls ); // 将控制器添加到场景中

			// 使用变换控制器时禁用轨道控制器
			transformControls.addEventListener( 'mouseDown', () => orbitControls.enabled = false );
			transformControls.addEventListener( 'mouseUp', () => orbitControls.enabled = true );

			// 将第一个骨骼添加到模型上
			OOI.kira.add( OOI.kira.skeleton.bones[ 0 ] );

			// 定义逆运动学参数
			const iks = [
				{
					target: 22, // "target_hand_l"
					effector: 6, // "hand_l"
					links: [
						{
							index: 5, // "lowerarm_l"
							rotationMin: new THREE.Vector3( 1.2, - 1.8, - .4 ),
							rotationMax: new THREE.Vector3( 1.7, - 1.1, .3 )
						},
						{
							index: 4, // "Upperarm_l"
							rotationMin: new THREE.Vector3( 0.1, - 0.7, - 1.8 ),
							rotationMax: new THREE.Vector3( 1.1, 0, - 1.4 )
						},
					],
				}
			];
			IKSolver = new CCDIKSolver( OOI.kira, iks ); // 创建逆运动学求解器
			const ccdikhelper = new CCDIKHelper( OOI.kira, iks, 0.01 ); // 创建逆运动学帮助器
			scene.add( ccdikhelper ); // 将逆运动学帮助器添加到场景中

			gui = new GUI(); // 创建GUI
			gui.add( conf, 'followSphere' ).name( 'follow sphere' ); // 添加跟随球体的控制项
			gui.add( conf, 'turnHead' ).name( 'turn head' ); // 添加转动头部的控制项
			gui.add( conf, 'ik_solver' ).name( 'IK auto update' ); // 添加逆运动学自动更新的控制项
			gui.add( conf, 'update' ).name( 'IK manual update()' ); // 添加手动更新逆运动学的控制项
			gui.open(); // 默认打开GUI

			window.addEventListener( 'resize', onWindowResize, false ); // 监听窗口大小变化事件
		}

		function animate( ) {
			// 更新镜像球体相机位置和渲染
			if ( OOI.sphere && mirrorSphereCamera ) {
				OOI.sphere.visible = false;
				OOI.sphere.getWorldPosition( mirrorSphereCamera.position );
				mirrorSphereCamera.update( renderer, scene );
				OOI.sphere.visible = true;
			}

			// 如果设置了跟随球体,轨道控制器将跟随球体位置
			if ( OOI.sphere && conf.followSphere ) {
				OOI.sphere.getWorldPosition( v0 );
				orbitControls.target.lerp( v0, 0.1 );
			}

			// 如果设置了转动头部,头部朝向球体
			if ( OOI.head && OOI.sphere && conf.turnHead ) {
				OOI.sphere.getWorldPosition( v0 );
				OOI.head.lookAt( v0 );
				OOI.head.rotation.set( OOI.head.rotation.x, OOI.head.rotation.y + Math.PI, OOI.head.rotation.z );
			}

			// 如果设置了逆运动学自动更新,更新逆运动学
			if ( conf.ik_solver ) {
				updateIK();
			}

			orbitControls.update(); // 更新轨道控制器
			renderer.render( scene, camera ); // 渲染场景
			stats.update(); // 更新性能统计

			requestAnimationFrame( animate ); // 请求下一帧动画
		}

		function updateIK() {
			// 更新逆运动学
			if ( IKSolver ) IKSolver.update();

			scene.traverse( function ( object ) {
				// 遍历场景中的对象
				if ( object.isSkinnedMesh ) object.computeBoundingSphere();
			} );
		}

		function onWindowResize() {
			// 窗口大小变化事件处理函数
			camera.aspect = window.innerWidth / window.innerHeight;
			camera.updateProjectionMatrix();
			renderer.setSize( window.innerWidth, window.innerHeight );
		}
		</script>
	</body>
</html>

本内容来源于小豆包,想要更多内容请跳转小豆包 》

相关推荐
烟锁池塘柳020 小时前
Camera ISP Pipeline(相机图像信号处理管线)
图像处理·数码相机·信号处理
3DVisionary20 小时前
XTOP3D的DIC技术在极端条件下的应用解决方案
数码相机·3d·航空工业·全场应变测量·航空机匣内部四测头同步测量·反射镜辅助dic观测·四测头方案
视觉人机器视觉3 天前
3D与2D机器视觉机械臂引导的区别
人工智能·数码相机·计算机视觉·3d·视觉检测
LabVIEW开发3 天前
LabVIEW开发中的电机控制与相机像素差
数码相机·labview
pixle04 天前
Three.js 快速入门教程【二】透视投影相机
开发语言·javascript·数码相机
go54631584654 天前
python实现将RGB相机与事件相机的照片信息进行融合以进行目标检测
python·数码相机·目标检测
看星猩的柴狗4 天前
ROS-相机话题-获取图像-颜色目标识别与定位-目标跟随-人脸检测
数码相机
彩云的笔记5 天前
相机快门 deepseek
数码相机
视觉人机器视觉5 天前
机器视觉检测中,2D面阵相机和线扫相机的区别
人工智能·数码相机·计算机视觉·3d·视觉检测
虾球xz5 天前
游戏引擎学习第110天
数码相机·学习·游戏引擎