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

目录

​编辑

1 骨架工具(SkeletonUtils)

 1.1 clone方法

2 蒙皮网格(SkinnedMesh)

3 自测

4 webgl_animation_multiple.html全部脚本


1 骨架工具(SkeletonUtils)

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

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

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切换时的参数打印

4 webgl_animation_multiple.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.mzph.cn/bicheng/24193.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络编程: 高级IO与多路转接select,poll,epoll的使用与介绍

网络编程: 高级IO与多路转接select,poll,epoll的使用与介绍 前言一.五种IO模型1.IO的本质2.五种IO模型1.五种IO模型2.同步IO与异步IO3.IO效率 二.非阻塞IO1.系统调用介绍2.验证代码 三.select多路转接1.系统调用接口2.写代码 : 基于select的TCP服务器1.封装的Socket接口2.开始写…

1-Maven-settings配置

1-Maven-settings配置 整理下Maven工具的使用。 【本地仓库、私服、镜像仓库、远程仓库、中央仓库】 本文基于阅读其他博客和对公司Maven配置的学习整理出来的。希望通过本此学习能对Maven有个整体性的掌控。 顺序&#xff1a;profile.repository > pom文件中的repository &…

asp.net core使用httpclient

主要讲解常见的get请求和post请求 GET var client new HttpClient(); //3秒钟不响应就超时 client.TimeoutTimeSpan.FromSeconds(3); using HttpResponseMessage response await client.GetAsync("todos/3"); var jsonResponse await response.Content.ReadAsSt…

postman测试接口(springboot+shiro)带token也不通的解决方案

前几天做项目遇到个问题&#xff0c;在系统可以正常使用的接口&#xff0c;拿postman带token访问时候确一直不通&#xff08;后台返回需要登录的提示信息&#xff09; 但是我明明加了token的呀 打断点发现 subject.isAuthenticated()false 查资料猜测可能是因为请求的安全上…

【WP】猿人学_16_js逆向_window蜜罐

https://match.yuanrenxue.cn/match/16 抓包分析 荷载一个加密参数&#xff0c;一个时间戳 时间: 2024-06-07 15:52:31时间戳: 1717746751 1717746751000时间戳和现在对得上&#xff0c;直接生成就行。 追栈 追栈找m的生成位置。 点进去打断点&#xff0c;重新点击其他…

C语言基础——函数

ʕ • ᴥ • ʔ づ♡ど &#x1f389; 欢迎点赞支持&#x1f389; 个人主页&#xff1a;励志不掉头发的内向程序员&#xff1b; 专栏主页&#xff1a;C语言基础&#xff1b; 文章目录 前言 一、函数的概念 二、库函数 2.1 库函数和头文件 2.2 库函数的使用/…

出售iPhone前的必做步骤:完全擦除个人数据的方法

当您准备在闲鱼上转售旧 iPhone、将其捐赠、送给朋友或通过 Apple 回收之前&#xff0c;您可能会选择执行“恢复”操作来擦除您的数据。但请注意&#xff0c;这一操作并不能真正删除设备中的数据。被“删除”或“格式化”的数据实际上仍存在于 iPhone 中&#xff0c;只是被系统…

SpringBoot+Vue在线文档管理系统(前后端分离)

技术栈 JavaSpringBootMavenMySQLMyBatisVueShiroElement-UI 系统角色对应功能 员工管理员 系统功能截图

《精通ChatGPT:从入门到大师的Prompt指南》第1章:认识ChatGPT

第1章&#xff1a;认识ChatGPT 1.1 ChatGPT是什么 ChatGPT&#xff0c;全称为Chat Generative Pre-trained Transformer&#xff0c;是由OpenAI开发的一种先进的自然语言处理模型。它利用了深度学习中的一种技术——Transformer架构&#xff0c;来生成类人文本。ChatGPT通过对…

贪心算法-数组跳跃游戏(mid)

目录 一、问题描述 二、解题思路 1.回溯法 2.贪心算法 三、代码实现 1.回溯法实现 2.贪心算法实现 四、刷题链接 一、问题描述 二、解题思路 1.回溯法 使用递归的方式&#xff0c;找到所有可能的走步方式&#xff0c;并记录递归深度&#xff08;也就是走步次数&#x…

玩转ChatGPT:最全学术论文提示词分享【上】

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 在当今数字时代&#xff0c;人工智能&#xff08;AI&#xff09;技术正迅速改变各行各业的运作方式。特别是&#xff0c;OpenAI的ChatGPT等语言模型以其强大的文本生成能力&#xff0c;…

【CTF MISC】XCTF GFSJ0170 János-the-Ripper Writeup(文件提取+ZIP压缩包+暴力破解)

Jnos-the-Ripper 暂无 解法 用 winhex 打开&#xff0c;提到了 flag.txt。 用 binwalk 扫描&#xff0c;找到一些 zip 压缩包。 binwalk misc100用 foremost 提取文件。 foremost misc100 -o 100flag.txt 在压缩包里。 但是压缩包需要解压密码。 用 Ziperello 暴力破解。 不…

mac安装nigix且配置 vue/springboot项目(本地/服务器)

一、mac安装Nigix 1. 查看是否存在 nginx 执行brew search nginx 命令查询要安装的软件是否存在 brew search nginx 2. 安装nginx brew install nginx 3. 查看版本 nginx -v 4. 查看信息 查看ngxin下载的位置以及nginx配置文件存放路径等信息 brew info nginx 下载的存…

Angular 由一个bug说起之六:字体预加载

浏览器在加载一个页面时&#xff0c;会解析网页中的html和css&#xff0c;并开始加载字体文件。字体文件可以通过css中的font-face规则指定&#xff0c;并使用url()函数指定字体文件的路径。 比如下面这样: css font-face {font-family: MyFont;src: url(path/to/font.woff2…

IDEA 中设置 jdk 的版本

本文介绍一下 IDEA 中设置 jdk 版本的步骤。 一共有三处需要配置。 第一处 File --> Project Structure Project 和 Modules 下都需要指定一下。 第二处 File --> Settings 第三处 运行时的配置

Linux基础2-基本指令4(cp,mv,cat,tac)

上篇文章我们说到了rmdir,rm,man,echo.重定向等知识。 Linux基础1-基本指令3-CSDN博客 本文继续梳理其他基础指令 1.本章重点 1.使用cp命令拷贝文件 2.使用mv命令移动文件 3.使用cat&#xff0c;tac查看小文本文件 2.cp命令 在linux中使用cp命令来拷贝粘贴文件 cp src(原文…

解决Nginx出现An error occurred问题

每个人遇到Nginx的An error occurred情况可能都不一样&#xff08;见图1&#xff09;&#xff0c;Nginx造成该错误的原因&#xff1a; 1. 我在配置域名解析成IP时&#xff0c;没有把所有解析配置都修改&#xff0c;见图2&#xff1a;解析 *.hanxiaozhang.xyz 配置的是新IP地…

Nvidia Jetson/Orin/算能 +FPGA+AI大算力边缘计算盒子:潍柴雷沃智慧农业无人驾驶

潍柴雷沃智慧农业科技股份有限公司&#xff0c;是潍柴集团重要的战略业务单元&#xff0c;旗下收获机械、拖拉机等业务连续多年保持行业领先&#xff0c;是国内少数可以为现代农业提供全程机械化整体解决方案的品牌之一。潍柴集团完成对潍柴雷沃智慧农业战略重组后&#xff0c;…

轻松解决问题!教你文件怎么解除只读模式!

在日常使用电脑时&#xff0c;我们有时会遇到文件或文件夹被设定为只读模式的情况&#xff0c;这可能会限制我们对文件的修改和编辑。然而&#xff0c;解除只读模式并获得文件的完全控制是一个相对简单的过程&#xff0c;只需要掌握一些基本的技巧和方法。在本文中&#xff0c;…

java版spring cloud 知识付费平台的功能模块与子模块划分

随着互联网技术的飞速发展&#xff0c;知识付费平台已经成为了我国在线教育领域的一颗新星。这些平台以用户需求为出发点&#xff0c;围绕高质量的内容打造&#xff0c;利用互联网技术为用户提供了一个便捷、高效的学习环境。它们汇聚了丰富的专业知识&#xff0c;覆盖了职业技…