学习threejs,通过SkinnedMesh来创建骨骼和蒙皮动画

👨‍⚕️ 主页: gis分享者
👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨‍⚕️ 收录于专栏:threejs gis工程师


文章目录

  • 一、🍀前言
    • 1.1 ☘️THREE.SkinnedMesh 蒙皮网格
  • 二、🍀通过SkinnedMesh来创建骨骼和蒙皮动画
    • 1. ☘️实现思路
    • 2. ☘️代码样例


一、🍀前言

本文详细介绍如何基于threejs在三维场景中通过SkinnedMesh来创建骨骼和蒙皮动画,亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️THREE.SkinnedMesh 蒙皮网格

THREE.SkinnedMesh具有Skeleton(骨架)和bones(骨骼)的网格,可用于给几何体上的顶点添加动画。 其材质必须支持蒙皮,并且已经启用了蒙皮
创建方法:
SkinnedMesh( geometry : BufferGeometry, material : Material )
geometry:一个BufferGeometry实例。
material:(可选)一个Material实例,默认值是一个新的MeshBasicMaterial。
属性:
bindMode:string “attached”(附加)或者“detached”(分离)。“attached”使用SkinnedMesh.matrixWorld 属性作为对骨骼的基本变换矩阵,“detached”则使用SkinnedMesh.bindMatrix。 默认值是“attached”。
bindMatrix:Matrix4 该基础矩阵用于绑定骨骼的变换。
bindMatrixInverse:Matrix4 该基础矩阵用于重置绑定骨骼的变换。
isSkinnedMesh:用于检查这个类或者其派生类是否为蒙皮网格,默认值为true。
skeleton:用于表示蒙皮网格中骨骼的层次结构的Skeleton(骨架)。
方法:
(1)bind ( skeleton : Skeleton, bindMatrix : Matrix4 ):null
skeleton —— 由一棵Bones树创建的Skeleton。
bindMatrix —— 表示骨架基本变换的Matrix4(4x4矩阵)。
将骨架绑定到一个蒙皮网格上。bindMatrix会被保存到.bindMatrix属性中,其逆矩阵.bindMatrixInverse也会被计算出来。
(2)clone () : SkinnedMesh
返回当前SkinnedMesh对象的一个克隆及其任何后代。
(3)normalizeSkinWeights () : null
标准化蒙皮的权重。
(4)pose ():null
这个方法设置了在“休息”状态下蒙皮网格的姿势(重置姿势)。
(5)updateMatrixWorld ( force : Boolean ) :null
更新MatrixWorld矩阵。

二、🍀通过SkinnedMesh来创建骨骼和蒙皮动画

1. ☘️实现思路

  • 1、初始化renderer渲染器
  • 2、初始化Scene三维场景
  • 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt。
  • 4、初始化THREE.AmbientLight环境光源,scene场景加入环境光源,初始化THREE.PointLight点光源,设置点光源位置,设置点光源投影,scene添加点光源。
  • 5、加载几何模型:创建THREE.AxesHelper坐标辅助工具,创建THREE.JSONLoader加载器加载hand1.js json模型文件,生成geometry几何体,根据生成的几何体创建THREE.SkinnedMesh蒙皮网格,设置mesh的旋转角度和位置。传入参数mesh创建THREE.SkeletonHelper可视化骨骼结构对象skeletonHelper。场景scene中加入mesh和skeletonHelper。创建间隔动画initTween,定义mesh的骨骼和蒙皮动画。具体代码参考代码样例。
  • 6、加入controls、gui控制(控制skeletonHelper的显示、隐藏和动画的播放),加入stats监控器,监控帧数信息。

2. ☘️代码样例

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>learn49(通过SkinnedMesh来创建骨骼和蒙皮动画)</title><!-- <script src="lib/threejs/127/three.js-master/build/three.js"></script><script src="lib/threejs/127/three.js-master/examples/js/controls/OrbitControls.js"></script>--><script src="lib/threejs/91/three.js"></script><script src="https://johnson2heng.github.io/three.js-demo/lib/js/controls/OrbitControls.js"></script><script src="https://cdn.bootcss.com/tween.js/r14/Tween.min.js"></script><script src="lib/threejs/127/three.js-master/examples/js/libs/stats.min.js"></script><script src="lib/threejs/127/three.js-master/examples/js/libs/dat.gui.min.js"></script><script src="lib/js/Detector.js"></script>
</head>
<style type="text/css">html, body {margin: 0;height: 100%;}canvas {display: block;}</style>
<body onload="draw()">
</body>
<script>var renderervar initRender = () => {renderer = new THREE.WebGLRenderer({antialias: true})renderer.setPixelRatio(window.devicePixelRatio)renderer.setSize(window.innerWidth, window.innerHeight)renderer.setClearColor(0xeeeeee)document.body.appendChild(renderer.domElement)}var scenevar initScene = () => {scene = new THREE.Scene()}var cameravar initCamera = () => {camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)camera.position.set(0, 40, 50)}var lightvar initLight = () => {scene.add(new THREE.AmbientLight(0x444444))light = new THREE.PointLight(0xffffff)light.position.set(0, 50, 0)light.castShadow = truescene.add(light)}var mesh, tween, skeletonHelpervar initModel = () => {var helper = new THREE.AxesHelper(50)scene.add(helper)var loader = new THREE.JSONLoader()loader.load('data/model/hand1/hand1.js', geometry => {mesh = new THREE.SkinnedMesh(geometry, new THREE.MeshLambertMaterial({color: 0xf4b397,skinning: true}))mesh.rotation.x = 0.5 * Math.PImesh.rotation.z = 0.7 * Math.PImesh.scale.set(10, 10, 10)skeletonHelper = new THREE.SkeletonHelper(mesh)skeletonHelper.visible = falsescene.add(skeletonHelper)scene.add(mesh)tween.start()})}var initTween = () => {tween = new TWEEN.Tween({pos: -1}).to({pos: 0}, 3000).easing(TWEEN.Easing.Cubic.InOut).yoyo(true).repeat(Infinity) //一直循环tween.onUpdate(function () {var pos = this.pos// 旋转手指的方向mesh.skeleton.bones[5].rotation.set(0, 0, pos)mesh.skeleton.bones[6].rotation.set(0, 0, pos)mesh.skeleton.bones[10].rotation.set(0, 0, pos)mesh.skeleton.bones[11].rotation.set(0, 0, pos)mesh.skeleton.bones[15].rotation.set(0, 0, pos)mesh.skeleton.bones[16].rotation.set(0, 0, pos)mesh.skeleton.bones[20].rotation.set(0, 0, pos)mesh.skeleton.bones[21].rotation.set(0, 0, pos)// 旋转手腕mesh.skeleton.bones[1].rotation.set(pos, 0, 0)})}var statsvar initStats = () => {stats = new Stats()document.body.appendChild(stats.dom)}var controlsvar initControls = () => {controls = new THREE.OrbitControls(camera, renderer.domElement)controls.enableDamping = true}var gui, animation = truevar initGui = () => {gui = {animation: true,helper: false}var datGui = new dat.GUI()datGui.add(gui, 'animation').onChange(e => {animation = e})datGui.add(gui, 'helper').onChange(e => {skeletonHelper.visible = e})}var render = () => {animation && TWEEN.update()controls.update()}var onWindowResize = () => {camera.aspect = window.innerWidth / window.innerHeightcamera.updateProjectionMatrix()renderer.setSize(window.innerWidth, window.innerHeight)}var animate = () => {render()stats.update()renderer.render(scene, camera)requestAnimationFrame(animate)}var draw = () => {if (!Detector.webgl) Detector.addGetWebGLMessage()initRender()initScene()initCamera()initLight()initModel()initControls()initStats()initGui()initTween()animate()window.onresize = onWindowResize}
</script>
</html>

效果如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/886726.shtml

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

相关文章

HarmonyOS NEXT应用元服务开发Intents Kit(意图框架服务)习惯推荐方案概述

一、习惯推荐是HarmonyOS学习用户的行为习惯后做出的主动预测推荐。 1.开发者将用户在应用/元服务内的使用行为向HarmonyOS共享&#xff0c;使得HarmonyOS可以基于共享的数据学习用户的行为习惯。 2.在HarmonyOS学习到用户的行为习惯后&#xff0c;会给用户推荐相应功能&#x…

华为防火墙技术基本概念学习笔记

1.防火墙概述 1.1防火墙与交换机、路由器对比 路由器与交换机的本质是转发&#xff0c;防火墙的本质是控制。 防火墙与路由器、交换机是有区别的。路由器用来连接不同的网络&#xff0c;通过路由协议保证互联互通&#xff0c;确保将报文转发到目的地;交换机则通常用来组建局域…

shell(5)字符串运算符和逻辑运算符

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…

帆软report参数栏宽度设置

最右边的竖杠被放大后在拉回来

Mysql-DQL语句

文章目录 DQL 语句简单查询查询表所有数据查询指定列 别名查询清除重复值查询结果参与运算 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Mysql专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月16日11点39分 DQL 语句 DQL 语句数据…

MySQL数据库3——函数与约束

一.函数 1.字符串函数 MySQL中内置了很多字符串函数&#xff0c;常用的几个如下&#xff1a; 使用方法&#xff1a; SELECT 函数名(参数);注意&#xff1a;MySQL中的索引值即下标都是从1开始的。 2.数值函数 常见的数值函数如下&#xff1a; 使用方法&#xff1a; SELECT…

Vue.js 插槽 Slots 实际应用 最近重构项目的时候遇到的...

前端开发中 插槽 Slots 是一个重要的概念 我们可以查看一下vue.js的官方文档 https://cn.vuejs.org/guide/components/slots 类似于连接通道一样 可以把核心代码逻辑搬到另外的地方 做一个引用 而原先的地方可能并不能这样书写 对于这个概念我在vue的官方文档里面找到了…

5G 现网信令参数学习(3) - RrcSetup(2)

前一篇&#xff1a;5G 现网信令参数学习(3) - RrcSetup(1) 目录 1. rlf-TimersAndConstants 2. spCellConfigDedicated 2.1 initialDownlinkBWP 2.1.1 pdcch-Config 2.1.1.1 controlResourceSetToAddModList 2.1.1.2 searchSpacesToAddModList 2.1.2 pdsch-Config 2.1…

《探索 C++:一门强大且多功能的编程语言》

《探索 C&#xff1a;一门强大且多功能的编程语言》 在编程的广阔世界里&#xff0c;C 无疑是一颗璀璨的明星&#xff0c;它以其高性能、丰富的特性和广泛的应用领域&#xff0c;吸引着无数开发者投身其中。今天&#xff0c;就让我们一同深入探索一下这门令人着迷的编程语言吧。…

MySQL(5)【数据类型 —— 字符串类型】

阅读导航 引言一、char&#x1f3af;基本语法&#x1f3af;使用示例 二、varchar&#x1f3af;基本语法&#x1f3af;使用示例 三、char 和 varchar 比较四、日期和时间类型1. 基本概念2. 使用示例 五、enum 和 set&#x1f3af;基本语法 引言 之前我们聊过MySQL中的数值类型&…

【蓝桥杯C/C++】翻转游戏:多种实现与解法解析

文章目录 &#x1f4af;题目&#x1f4af;问题分析解法一&#xff1a;减法法解法二&#xff1a;位运算解法解法三&#xff1a;逻辑非解法解法四&#xff1a;条件运算符解法解法五&#xff1a;数组映射法不同解法的比较 &#x1f4af;小结 &#x1f4af;题目 在蓝桥镇&#xff0…

深度学习之人脸检测

在目标检测领域可以划分为了人脸检测与通用目标检测&#xff0c;往往人脸这方面会有专门的算法&#xff08;包括人脸检测、人脸识别、人脸其他属性的识别等等&#xff09;&#xff0c;并且和通用目标检测&#xff08;识别&#xff09;会有一定的差别&#xff0c;着主要来源于人…

docker busybox作为initContainers

一、上传到私有仓储 docker pull busybox:1.33.1 docker tag busybox:1.33.1 192.168.31.185/public/busybox:1.33.1 docker push 192.168.31.185/public/busybox:1.33.1 --- apiVersion: apps/v1 kind: Deploymentspec:containers:- env:- name: ASPNETCORE_ENVIRONMENTvalue…

Java实现两数交换

文章目录 实现两数交换方法一、&#xff08;数组的方式进行交换&#xff09;方法二、&#xff08;对象的方式进行交换&#xff09;总结 实现两数交换 实现两数交换&#xff0c;没有办法通过直接传递数字达到交换的结果&#xff0c;定义的int型变量是被存储在栈空间上的&#xf…

人工智能在金融领域的应用与风险防范研究

人工智能在金融领域的应用与风险防范研究 摘要&#xff1a;随着人工智能技术的不断进步&#xff0c;其在金融领域的应用日益广泛&#xff0c;同时也带来了新的风险与挑战。本文首先分析了人工智能在金融领域的主要应用场景&#xff0c;如智能投顾、信贷风险评估和反欺诈等。接着…

数据结构(二)线性表

线性表&#xff0c;也称为线性结构&#xff0c;是数据结构中的一种基本类型&#xff0c;其特点是数据元素之间存在一对一的线性关系。线性表通常可以用数组&#xff08;顺序存储&#xff09;或链表&#xff08;链式存储&#xff09;来实现。线性表的特点是数据元素的排列呈现线…

SQLite3 JDBC Java工具类

最近生产环境mysql各种无法使用&#xff0c;要求下线。有一堆小工具&#xff0c;平时因为mysql用着方便&#xff0c;配置啊&#xff0c;临时的一些比对数据存在里面。迁移很麻烦。 发现SQLite 3.47.0版本之后&#xff0c;性能大增&#xff0c;支持多线程&#xff0c;记录级锁。…

招聘和面试

本篇内容是根据2019年4月份#82 Hiring and job interviews音频录制内容的整理与翻译 小组成员 Mat Ryer、Ashley McNamara、Johnny Boursiquot 和 Carmen Andoh 讨论了受聘、雇用和工作面试的过程。如果人是团队中最重要的部分&#xff0c;我们如何选择与谁一起工作&#xff1…

【代码随想录|回溯算法排列问题】

491.非减子序列 题目链接. - 力扣&#xff08;LeetCode&#xff09; 这里和子集问题||很像&#xff0c;但是这里要的是非递减的子序列&#xff0c;要按照给的数组的顺序来进行排序&#xff0c;就是如果我给定的数组是[4,4,3,2,1]&#xff0c;如果用子集||的做法先进行排序得到…

GOLANG+VUE后台管理系统

1.截图 2.后端工程截图 3.前端工程截图