React + three.js 3D模型面部表情控制

系列文章目录

  1. React 使用 three.js 加载 gltf 3D模型 | three.js 入门
  2. React + three.js 3D模型骨骼绑定
  3. React + three.js 3D模型面部表情控制

示例项目(github):https://github.com/couchette/simple-react-three-facial-expression-demo
示例项目(gitcode):https://gitcode.com/qq_41456316/simple-react-three-facial-expression-demo

文章目录

  • 系列文章目录
  • 前言
  • 一、实现步骤
    • 1、创建项目配置环境
    • 2. 创建组件
    • 3. 使用组件
    • 4. 运行项目
  • 总结


前言

在本系列的上一篇文章中,我们已经探讨了如何在 React 中利用 three.js 来渲染 3D 模型,现在,我们将深入研究如何运用 three.js 控制这些模型的表情。让我们一同探索如何赋予你的 3D 模型更加生动和丰富的表情吧!


一、实现步骤

1、创建项目配置环境

使用 create-reacte-app 创建项目

npx create-react-app simple-react-three-facial-expression-demo
cd simple-react-three-facial-expression-demo

安装three.js

npm i three

2. 创建组件

src目录创建components文件夹,在components文件夹下面创建ThreeContainer.js文件。
首先创建组件,并获取return 元素的ref

import * as THREE from "three";
import { useRef, useEffect } from "react";function ThreeContainer() {const containerRef = useRef(null);const isContainerRunning = useRef(false);return <div ref={containerRef} />;
}export default ThreeContainer;

接着将three.js自动创建渲染元素添加到return组件中为子元素(可见container.appendChild(renderer.domElement);),相关逻辑代码在useEffect中执行,完整代码内容如下

import * as THREE from "three";import WebGPU from "three/addons/capabilities/WebGPU.js";
import WebGL from "three/addons/capabilities/WebGL.js";import WebGPURenderer from "three/addons/renderers/webgpu/WebGPURenderer.js";import Stats from "three/addons/libs/stats.module.js";import { OrbitControls } from "three/addons/controls/OrbitControls.js";import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { KTX2Loader } from "three/addons/loaders/KTX2Loader.js";
import { MeshoptDecoder } from "three/addons/libs/meshopt_decoder.module.js";import { GUI } from "three/addons/libs/lil-gui.module.min.js";
import { useRef, useEffect } from "react";function ThreeContainer() {const containerRef = useRef(null);const isContainerRunning = useRef(false);useEffect(() => {if (!isContainerRunning.current && containerRef.current) {isContainerRunning.current = true;init();}async function init() {if (WebGPU.isAvailable() === false &&WebGL.isWebGL2Available() === false) {containerRef.current.appendChild(WebGPU.getErrorMessage());throw new Error("No WebGPU or WebGL2 support");}let mixer;const clock = new THREE.Clock();const container = containerRef.current;const camera = new THREE.PerspectiveCamera(45,window.innerWidth / window.innerHeight,1,20);camera.position.set(-1.8, 0.8, 3);const scene = new THREE.Scene();scene.add(new THREE.HemisphereLight(0xffffff, 0x443333, 2));const renderer = new WebGPURenderer({ antialias: true });renderer.setPixelRatio(window.devicePixelRatio);renderer.setSize(window.innerWidth, window.innerHeight);renderer.toneMapping = THREE.ACESFilmicToneMapping;renderer.setAnimationLoop(animate);container.appendChild(renderer.domElement);const ktx2Loader = await new KTX2Loader().setTranscoderPath("/basis/").detectSupportAsync(renderer);new GLTFLoader().setKTX2Loader(ktx2Loader).setMeshoptDecoder(MeshoptDecoder).load("models/facecap.glb", (gltf) => {const mesh = gltf.scene.children[0];scene.add(mesh);mixer = new THREE.AnimationMixer(mesh);mixer.clipAction(gltf.animations[0]).play();// GUIconst head = mesh.getObjectByName("mesh_2");const influences = head.morphTargetInfluences;//head.morphTargetInfluences = null;// WebGPURenderer: Unsupported texture format. 33776head.material.map = null;const gui = new GUI();gui.close();for (const [key, value] of Object.entries(head.morphTargetDictionary)) {gui.add(influences, value, 0, 1, 0.01).name(key.replace("blendShape1.", "")).listen();}});scene.background = new THREE.Color(0x666666);const controls = new OrbitControls(camera, renderer.domElement);controls.enableDamping = true;controls.minDistance = 2.5;controls.maxDistance = 5;controls.minAzimuthAngle = -Math.PI / 2;controls.maxAzimuthAngle = Math.PI / 2;controls.maxPolarAngle = Math.PI / 1.8;controls.target.set(0, 0.15, -0.2);const stats = new Stats();container.appendChild(stats.dom);function animate() {const delta = clock.getDelta();if (mixer) {mixer.update(delta);}renderer.render(scene, camera);controls.update();stats.update();}window.addEventListener("resize", () => {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);});}}, []);return <div ref={containerRef} />;
}export default ThreeContainer;

3. 使用组件

修改App.js的内容如下

import "./App.css";
import ThreeContainer from "./components/ThreeContainer";function App() {return (<div><ThreeContainer /></div>);
}export default App;

4. 运行项目

运行项目npm start最终效果如下
请添加图片描述


总结

通过本文的介绍,相信读者对于在 React 中实现 3D 模型表情控制有了初步的了解。如果你对此感兴趣,不妨动手尝试一下,可能会有意想不到的收获。同时,也欢迎大家多多探索,将 React 和 Three.js 的强大功能发挥到极致,为网页应用增添更多的乐趣和惊喜。

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

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

相关文章

云上配置Hadoop环境

Hadoop概述 Hadoop技术主要是由下面这三个组件组合而成的&#xff1a; HDFS是一个典型的主从模式架构。 HDFS的基础架构 HDFS的集群搭建 一点准备工作 其实这一块没啥内容&#xff0c;就是将Hadoop官网下载下来的Hadoop的tar包上传到我们服务器上的文件目录下&#xff1a; …

深入浅出 -- 系统架构之日均亿级吞吐量的网关架构(DNS轮询解析)

在前篇关于《Nginx》的文章中曾经提到&#xff1a;单节点的Nginx在经过调优后&#xff0c;可承载5W左右的并发量&#xff0c;同时为确保Nginx的高可用&#xff0c;在文中也结合了Keepalived对其实现了程序宕机重启、主机下线从机顶替等功能。 但就算实现了高可用的Nginx依旧存在…

LabVIEW无线快速存取记录器(WQAR)测试平台

LabVIEW无线快速存取记录器&#xff08;WQAR&#xff09;测试平台 随着民用航空业的迅速发展&#xff0c;航空安全的保障日益成为公众和专业领域的关注焦点。无线快速存取记录器&#xff08;WirelessQuick Access Recorder, WQAR&#xff09;作为记录飞行数据、监控飞行品质的…

从一个锚点到一座港湾:华为加速“巨幕手机”时代到来

不久之前&#xff0c;一位朋友跟我说&#xff0c;追了综艺《毛雪汪》之后&#xff0c;突然对许久不碰的电视有了兴趣。因为毛雪汪客厅里&#xff0c;好朋友一起用华为智慧屏 V5 系列玩大屏游戏&#xff0c;分享投屏视频的感觉特别好&#xff0c;满足了他对梦中电视的期待。 听到…

基于Vue的宠物领养系统的设计与实现(论文+源码)_kaic

目 录 摘 要 ABSTRACT 1 引言 1.1 课题背景 1.2 设计原则 1.3 论文组织结构 2 系统关键技术 2.1 JSP技术 2.2 JAVA技术 2.3 B/S结构 2.4 MYSQL数据库 3 系统分析 3.1 可行性分析 3.1.1 操作可行性 3.1.2 经济可行性 3.1.3 技术可行性 3.1.4 法律可行性 3.2 系统功能分析 3.3…

Post表单提交后端接不到参数

项目背景&#xff1a; 框架&#xff1a;Springboot 版本&#xff1a;1.5.6.REAEASE 问题描述 Postman通过表单提交请求时后端接不到值 原因分析&#xff1a; 启动项中注入其他Bean时取名叫dispatcherServlet&#xff0c;当发现http接口无法访问时&#xff0c;原开发人员又…

JS-28-AJAX

一、AJAX的定义 AJAX不是JavaScript的规范&#xff0c;它只是一个哥们“发明”的缩写&#xff1a;Asynchronous JavaScript and XML&#xff0c;意思就是用JavaScript执行异步网络请求。 如果仔细观察一个Form的提交&#xff0c;你就会发现&#xff0c;一旦用户点击“Submit”…

【AI面试】FPN、PANet、SPP、ASPP、Adaptive feature pooling

经常可以看到各个论文发出来,加入的各种trick。这些改进点,一般都是在前人的基础上,进行了一些修改。比如FPN到PANet的改进,就是为了改进前者存在的一些问题。 这里就把这些trick,给汇集到一起,看看他们的发展历史,看看他们之间有什么区别,又是在哪些地方做的改进。这…

【RV1106的ISP使用记录之一】基础环境搭建

公司缺少ISP工程师&#xff0c;做为图像算法工程师的我这就不就给顶上来了么&#xff0c;也没给发两份工资&#xff0c;唉~ 先写个标题&#xff0c;占一个新坑&#xff0c;记录RK平台的传统ISP工作。 一、基础环境的硬件包括三部分&#xff1a; 1、相机环境&#xff0c;用于采…

华为海思数字芯片设计笔试第四套

声明 下面的题目作答都是自己认为正确的答案&#xff0c;并非官方答案&#xff0c;如果有不同的意见&#xff0c;可以评论区交流。 这些题目也是笔者从各个地方收集的&#xff0c;感觉有些题目答案并不正确&#xff0c;所以在个别题目会给出自己的见解&#xff0c;欢迎大家讨论…

Ubuntu (Linux系统) 下载安装 Qt 环境

在官网http://download.qt.io/archive/qt/ 下载安装包&#xff0c;默认linux平台下提供的安装包以run后缀结尾 也可以选择其它地址下载 Qt官网下载地址&#xff1a;https://download.qt.io&#xff1b; 国内镜像下载地址&#xff1a;https://mirrors.cloud.tencent.com/qt/ 。建…

量子城域网系列(二):量子密钥与通信系统中各层协议融合应用

写在前面。国家标准中对量子保密通信的定义&#xff1a;量子保密通信是利用QKD与其他密码技术结合形成的保密通信技术。 经过这段时间的讨论&#xff0c;我们基本上明白了量子保密通信的内涵、基础协议、技术原理等。我们知道了当前语境下的量子密钥分发网络核心是实现两点之间…

windows下pycharm中配置conda虚拟环境

目录 一&#xff1a;背景 二&#xff1a;安装conda环境 三&#xff1a;pycharm配置环境 四&#xff1a;注意问题 一&#xff1a;背景 在使用python的过程中&#xff0c;我们可能需要在一个windows环境中创建多个版本的python和安装不同的库去做一些开发任务。 使用conda&a…

文献学习-33-一个用于生成手术视频摘要的python库

VideoSum: A Python Library for Surgical Video Summarization Authors: Luis C. Garcia-Peraza-Herrera, Sebastien Ourselin, and Tom Vercauteren Source: https://arxiv.org/pdf/2303.10173.pdf 这篇文章主要关注的是如何通过视频摘要来简化和可视化手术视频&#xff0c…

【linux】set ff=unix、linux设置文件格式

文章目录 一、文件格式二、如何查看文件格式三、设置文件格式、set ffunix四、查看unix与dos的区别 一、文件格式 当我们打开sh脚本时发现有时候格式是unix(LF) ,有时候是windows(CR LF) 。如下图&#xff1a; 文件格式影响了文件中的换行符 linux中sh类型的文件一般要设置为…

文献速递:深度学习肝脏肿瘤诊断---动态对比增强 MRI 上的自动肝脏肿瘤分割使用 4D 信息:基于 3D 卷积和卷积 LSTM 的深度学习模型

Title 题目 Automatic Liver Tumor Segmentation on Dynamic Contrast Enhanced MRI Using 4D Information: Deep Learning Model Based on 3D Convolution and Convolutional LSTM 动态对比增强 MRI 上的自动肝脏肿瘤分割使用 4D 信息&#xff1a;基于 3D 卷积和卷积 LSTM …

K8s拉取habor镜像

目录 在daemon.json中添加仓库地址 重新加载daemon.json并重启docker 在目标node节点添加域名 验证目标node是否能正常登录镜像仓库 创建pod资源 加载yml文件 验证 查看pod的ip与端口号 在daemon.json中添加仓库地址 此处需要在创建资源对象所在的节点进行添加 路径&a…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十 简单视频浮雕画效果

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十 简单视频浮雕画效果 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十 简单视频浮雕画效果 一、简单介绍 二、简单视频浮雕画效果实现原理 三、简单视频浮雕画效果…

避免使用第三方工具完成电脑环境检测

0. 简介 在之前配置各种深度学习环境的时候经常需要先检测一下电脑的软硬件环境&#xff0c;其实整个过程比较重复和固定&#xff0c;所以我们是否有可能一键检测Python版本、PIP版本、Conda版本、CUDA版本、电脑系统、CPU核数、CPU频率、内存、硬盘等内容这是很多Deepper苦恼…

废品回收小程序推动回收行业的发展趋势

回收在全球都是一个重要行业&#xff0c;它为全球的环保作出了重要贡献。 随着科技的不断发展创新&#xff0c;废品回收的方式也逐渐多样&#xff0c;全新的线上回收小程序也逐渐出现在大众的生活中&#xff0c;在当下的手机时代&#xff0c;线上回收也为大众提供了更加便利的…