three.js官方案例(animation / multiple)webgl_animation_multiple.html学习笔记

ops/2024/10/18 14:23:19/
htmledit_views">

目录

​编辑

1 骨架工具(SkeletonUtils)

 1.1 clone方法

2 蒙皮网格(SkinnedMesh)

3 自测

html" title=webgl>webgl_animation_multiple.html%E5%85%A8%E9%83%A8%E8%84%9A%E6%9C%AC-toc" style="margin-left:40px;">4 html" title=webgl>webgl_animation_multiple.html全部脚本


1 骨架工具(SkeletonUtils)

用于操控 Skeleton、 SkinnedMesh、和 Bone 的实用方法。

SkeletonUtils 是一个附加组件,必须显式导入。 See Installation / Addons.

html" title=javascript>javascript">import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js';

 1.1 clone方法

//.clone ( object : Object3D ) : Object3D

///克隆给定对象及其后代,确保任何 SkinnedMesh 实例都与其骨骼正确关联。同时,骨骼也会被克隆,且必须是传递给此方法的物体的后代。而其他数据,如几何形状和材料,是通过引用来实现重复使用的

2 蒙皮网格(SkinnedMesh)

  console.log('model:',model);

  console.log('动画:',animations);

3 自测

测试蒙皮网格的一些脚本

只把蒙皮添加到scene里:

把model和蒙皮都添加到scene里:

把骨骼加到场景里

把雾的一行注掉,加上控制器,鼠标滚动视角边远看着是如下图所示:

修正模型大小:

model3.bindMode = THREE.DetachedBindMode;//注掉后模型也会变大

参考博客:

深度解析3D骨骼系统中骨骼运动对几何体顶点运动的影响

介绍了 D骨骼系统中骨骼几何体顶点的影响。

console.log(params);

这里是UI切换时的参数打印

html" title=webgl>webgl_animation_multiple.html%E5%85%A8%E9%83%A8%E8%84%9A%E6%9C%AC">4 html" title=webgl>webgl_animation_multiple.html全部脚本

html"><!DOCTYPE html>
<html lang="en"><head><title>Multiple animated skinned meshes</title><meta charset="utf-8"><meta content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" name="viewport"><link type="text/css" rel="stylesheet" href="main.css"></head><body><div id="info">This demo shows the usage of <strong>SkeletonUtils.clone()</strong> and how to setup a shared skeleton.<br/>Soldier model from <a href="https://www.mixamo.com" target="_blank" rel="noopener">https://www.mixamo.com</a>.</div><script type="importmap">{"imports": {"three": "../build/three.module.js","three/addons/": "./jsm/"}}</script><script type="module">import * as THREE from 'three';//gltf模型下载器import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';//骨架工具import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js';//uiimport { GUI } from 'three/addons/libs/lil-gui.module.min.js';//控制器//控制器import { OrbitControls } from 'three/addons/controls/OrbitControls.js';let camera, scene, renderer, clock;let model, animations;let controls;const mixers = [], objects = [];const params = {sharedSkeleton: false};init();animate();function init() {//相机camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );camera.position.set( 2, 3, - 6 );camera.lookAt( 0, 1, 0 );clock = new THREE.Clock();//场景scene = new THREE.Scene();scene.background = new THREE.Color( 0xa0a0a0 );//scene.fog = new THREE.Fog( 0xa0a0a0, 10, 50 );//半球光  (不能投射阴影)const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x8d8d8d, 3 );hemiLight.position.set( 0, 20, 0 );scene.add( hemiLight );//模拟的太阳const dirLight = new THREE.DirectionalLight( 0xffffff, 3 );dirLight.position.set( - 3, 10, - 10 );dirLight.castShadow = true;dirLight.shadow.camera.top = 4;dirLight.shadow.camera.bottom = - 4;dirLight.shadow.camera.left = - 4;dirLight.shadow.camera.right = 4;dirLight.shadow.camera.near = 0.1;dirLight.shadow.camera.far = 40;scene.add( dirLight );// scene.add( new THREE.CameraHelper( dirLight.shadow.camera ) );// ground 地面const mesh = new THREE.Mesh( new THREE.PlaneGeometry( 200, 200 ), new THREE.MeshPhongMaterial( { color: 0xcbcbcb, depthWrite: false } ) );mesh.rotation.x = - Math.PI / 2;mesh.receiveShadow = true;scene.add( mesh );const loader = new GLTFLoader();loader.load( 'models/gltf/Soldier.glb', function ( gltf ) {model = gltf.scene;animations = gltf.animations;console.log('model:',model);console.log('动画:',animations);model.traverse( function ( object ) {if ( object.isMesh ) object.castShadow = true;} );setupDefaultScene();//测试// const shareSkinnedMesh = model.getObjectByName( 'vanguard_Mesh' ); //获取蒙皮// const shareSkinnedMesh2 = model.getObjectByName( 'vanguard_visor' ); //获取蒙皮// const sharedSkeleton = shareSkinnedMesh.skeleton; //.skeleton 用于表示蒙皮网格中骨骼的层次结构的Skeleton(骨架)// const sharedParentBone = model.getObjectByName( 'mixamorigHips' );//骨骼// scene.add( sharedParentBone );// model.scale.setScalar( 0.01 );// model.rotation.x = - Math.PI * 0.5;  //这没起作用// scene.add(model);// const model1=shareSkinnedMesh.clone()// model1.bindMode = THREE.DetachedBindMode;// shareSkinnedMesh.clone().position.x=1;// const identity = new THREE.Matrix4();//骨骼的变换// model1.bind( sharedSkeleton, identity );//绑定// model1.position.x = - 2;// model1.scale.setScalar( 0.01 );// model1.rotation.x = - Math.PI * 0.5; //变正常了// scene.add(model1);} );//渲染器renderer = new THREE.WebGLRenderer( { antialias: true } );renderer.setPixelRatio( window.devicePixelRatio );renderer.setSize( window.innerWidth, window.innerHeight );renderer.shadowMap.enabled = true;document.body.appendChild( renderer.domElement );controls=new OrbitControls(camera, renderer.domElement);window.addEventListener( 'resize', onWindowResize );//UI部分const gui = new GUI();gui.add( params, 'sharedSkeleton' ).onChange( function () {clearScene();//console.log(params);if ( params.sharedSkeleton === true ) {setupSharedSkeletonScene();} else {setupDefaultScene();}} );gui.open();}function clearScene() {for ( const mixer of mixers ) {mixer.stopAllAction();//停止所有动作}mixers.length = 0;//for ( const object of objects ) {scene.remove( object );scene.traverse( function ( child ) {//蒙皮网格 SkinnedMesh//.skeleton 用于表示蒙皮网格中骨骼的层次结构的Skeleton(骨架)//dispose 释放该实例分配的GPU相关资源。每当您的应用程序中不再使用此实例时,请调用此方法if ( child.isSkinnedMesh ) child.skeleton.dispose();} );}}function setupDefaultScene() {// three cloned models with independent skeletons.三个具有单个共享骨架的克隆模型。// each model can have its own animation state  每个模型都可以有自己的动画状态//.clone ( object : Object3D ) : Object3D
//克隆给定对象及其后代,确保任何 SkinnedMesh 实例都与其骨骼正确关联。同时,骨骼也会被克隆,且必须是传递给此方法的物体的后代。而其他数据,如几何形状和材料,是通过引用来实现重复使用的。const model1 = SkeletonUtils.clone( model );const model2 = SkeletonUtils.clone( model );const model3 = SkeletonUtils.clone( model );const model4 = SkeletonUtils.clone( model );model1.position.x = - 2;model2.position.x = 0;model3.position.x = 2;model4.position.z = 2;
//分别获取每个的动画混合器const mixer1 = new THREE.AnimationMixer( model1 );const mixer2 = new THREE.AnimationMixer( model2 );const mixer3 = new THREE.AnimationMixer( model3 );const mixer4 = new THREE.AnimationMixer( model4 );mixer1.clipAction( animations[ 0 ] ).play(); // idlemixer2.clipAction( animations[ 1 ] ).play(); // runmixer3.clipAction( animations[ 3 ] ).play(); // walkmixer4.clipAction( animations[ 2 ] ).play(); //Tposescene.add( model1, model2, model3,model4 );//加到场景里objects.push( model1, model2, model3, model4);mixers.push( mixer1, mixer2, mixer3, mixer4);}function setupSharedSkeletonScene() {// three cloned models with a single shared skeleton. 三个具有单个共享骨架的克隆模型。// all models share the same animation state 。所有模型共享相同的动画状态const sharedModel = SkeletonUtils.clone( model );const shareSkinnedMesh = sharedModel.getObjectByName( 'vanguard_Mesh' ); //获取蒙皮const sharedSkeleton = shareSkinnedMesh.skeleton; //.skeleton 用于表示蒙皮网格中骨骼的层次结构的Skeleton(骨架)const sharedParentBone = sharedModel.getObjectByName( 'mixamorigHips' );//骨骼scene.add( sharedParentBone ); // the bones need to be in the scene for the animation to work 骨骼需要在场景中才能使动画工作const model1 = shareSkinnedMesh.clone();//这里是对蒙皮进行克隆const model2 = shareSkinnedMesh.clone();const model3 = shareSkinnedMesh.clone();const model4 = shareSkinnedMesh.clone();//bindMode表示蒙皮网格 与骷髅共享相同的世界空间model1.bindMode = THREE.DetachedBindMode; 绑定模式model2.bindMode = THREE.DetachedBindMode;model3.bindMode = THREE.DetachedBindMode;//注掉后模型也会变大model4.bindMode = THREE.DetachedBindMode;const identity = new THREE.Matrix4();// 绑定的矩阵model1.bind( sharedSkeleton, identity );//绑定model2.bind( sharedSkeleton, identity );model3.bind( sharedSkeleton, identity );model4.bind( sharedSkeleton, identity );model1.position.x = - 2;model2.position.x = 0;model3.position.x = 2;model4.position.z = 2;// apply transformation from the glTF asset 应用glTF资产的转换model1.scale.setScalar( 0.01 );model1.rotation.x = - Math.PI * 0.5;model2.scale.setScalar( 0.01 );model2.rotation.x = - Math.PI * 0.5;model3.scale.setScalar( 0.01 );model3.rotation.x = - Math.PI * 0.5;model4.scale.setScalar( 0.01 );model4.rotation.x = - Math.PI * 0.5;const mixer = new THREE.AnimationMixer( sharedParentBone );mixer.clipAction( animations[ 1 ] ).play();scene.add( sharedParentBone, model1, model2, model3 , model4);objects.push( sharedParentBone, model1, model2, model3, model4 );mixers.push( mixer );}function onWindowResize() {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize( window.innerWidth, window.innerHeight );}function animate() {requestAnimationFrame( animate );const delta = clock.getDelta();for ( const mixer of mixers ) mixer.update( delta );renderer.render( scene, camera );controls.update();}</script></body></html>


http://www.ppmy.cn/ops/47814.html

相关文章

el-dialog给弹框标题后加图标,鼠标悬停显示详细内容

效果&#xff1a; 代码&#xff1a; <div slot"title" class"el-dialog__title">标题<el-tooltip effect"dark" placement"right"><div slot"content">鼠标悬停显示</div><i class"el-icon…

云原生架构相关技术_2.云原生微服务

1.微服务发展背景 微服务模式将后端单体应用拆分为松耦合的多个子应用&#xff0c;每个子应用负责一组子功能。这些子应用称为“微服务”&#xff0c;多个“微服务”共同形成了一个物理独立但逻辑完整的分布式微服务体系。这些微服务相对独立&#xff0c;通过解耦研发、测试与部…

Codeforces Round 950 (Div. 3)

好久没写题解了&#xff0c;今天来写个题解。 A - 问题 Generator #include "bits/stdc.h" using namespace std;#define int long long #define endl \n #define IOS ios::sync_with_stdio(0),cin.tie(0); #define all(x) x.begin(),x.end() #define pi pair<in…

【网络安全的神秘世界】VsCode直连虚拟机

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 通过VsCode连接虚拟机&#xff0c;可以进行远程操作 在vscode里安装以下插件&#xff1a; Docker Dev Containers Remote Development Remote ssh 配…

TESSENT2024.1安装

一、安装过程参考Calibre安装过程&#xff08;此处省略&#xff0c;不再赘述&#xff09; 二、安装license管理器&#xff1a; SiemensLicenseServer_v2.2.1.0_Lnx64_x86-64.bin 三、Patch补丁&#xff1a; tessent安装目录和license管理安装目录&#xff0c;执行FlexNetLic…

五种主流数据库:常用数据类型

在设计数据库的表结构时&#xff0c;我们需要明确表中包含哪些字段以及字段的数据类型。字段的数据类型定义了该字段能够存储的数据种类以及支持的操作。 本文将会介绍五种主流数据库中常用的数据类型以及如何选择合适的数据类型&#xff0c;包括 MySQL、Oracle、SQL Server、…

别让你的品牌默默无闻,掌握建设与营销的关键技巧……

管理学大师彼得德鲁克曾经说过&#xff0c;“企业两个最重要的功能是创新和营销&#xff0c;其他一切都是成本。” 在商业领域中&#xff0c;有很多类型的营销。 它们中的每一个都不同&#xff0c;且都是有特定场景的。 有些用于区别于竞争对手&#xff0c;有些用于适应用户…

一些关于科技的想法

一、背景 1、自从有了科技&#xff0c;生产力快速发展&#xff0c;可以生产很多以前没有的产品&#xff0c;扩展人的交通、沟通交流、食物生产、物质流通等方面&#xff0c;还能提供超出想象的服务(基因治疗、人造器官、辐射育种、特种材料等等)。 2、有了不断发展的科技&…