使用 Three.js 创建一个 3D 人形机器人仿真系统

引言

在这篇文章中,我们将探讨如何使用 Three.js 创建一个简单但有趣的 3D 人形机器人仿真系统。这个机器人可以通过键盘控制进行行走和转向,并具有基本的动画效果。

在这里插入图片描述

技术栈

  • HTML5
  • Three.js
  • JavaScript

实现步骤

1. 基础设置

首先,我们需要创建基本的 HTML 结构并引入 Three.js 库:

<!DOCTYPE html>
<html>
<head><title>3D Robot Simulation</title><style>body { margin: 0; overflow: hidden;}canvas { display: block; }#info {position: absolute;top: 10px;left: 10px;color: white;font-family: Arial;font-size: 14px;background: rgba(0,0,0,0.5);padding: 10px;}</style>
</head>
<body><div id="info">使用方向键控制机器人:<br>↑ - 向前移动<br>← → - 左右转向</div><script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
</body>
</html>

2. 场景初始化

接下来,我们需要初始化 Three.js 的基本组件:

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87CEEB); // 天空蓝色背景const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);

3. 创建机器人类

创建一个 Robot 类来管理机器人的所有组件和动作:

class Robot {constructor() {this.body = new THREE.Group();// 创建躯干const torsoGeometry = new THREE.BoxGeometry(2, 3, 1);const torsoMaterial = new THREE.MeshPhongMaterial({color: 0x999999});this.torso = new THREE.Mesh(torsoGeometry, torsoMaterial);this.torso.castShadow = true;// 创建头部const headGeometry = new THREE.SphereGeometry(0.5);const headMaterial = new THREE.MeshPhongMaterial({color: 0xcccccc});this.head = new THREE.Mesh(headGeometry, headMaterial);this.head.position.y = 2;this.head.castShadow = true;// ... 其他部件的创建代码 ...}// 创建四肢createLimb(width, height) {const geometry = new THREE.BoxGeometry(width, height, width);const material = new THREE.MeshPhongMaterial({color: 0x999999});const limb = new THREE.Mesh(geometry, material);limb.castShadow = true;return limb;}// 行走动画walk() {const legRotation = Math.sin(Date.now() * 0.005) * 0.5;this.leftLeg.rotation.x = legRotation;this.rightLeg.rotation.x = -legRotation;const armRotation = Math.sin(Date.now() * 0.005) * 0.25;this.leftArm.rotation.x = -armRotation;this.rightArm.rotation.x = armRotation;}// 转向和移动方法turn(angle) {this.body.rotation.y += angle;}moveForward(speed) {this.body.position.x += Math.sin(this.body.rotation.y) * speed;this.body.position.z += Math.cos(this.body.rotation.y) * speed;}
}

4. 添加环境元素

创建地面和光照系统:

// 创建地面
const groundGeometry = new THREE.PlaneGeometry(100, 100);
const groundMaterial = new THREE.MeshPhongMaterial({ color: 0x808080,side: THREE.DoubleSide
});
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.position.y = -2.5;
ground.receiveShadow = true;
scene.add(ground);// 添加光源
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 10, 5);
directionalLight.castShadow = true;
scene.add(directionalLight);const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);

5. 实现控制系统

添加键盘控制和动画循环:

const keyStates = {};document.addEventListener('keydown', (e) => {keyStates[e.key] = true;
});document.addEventListener('keyup', (e) => {keyStates[e.key] = false;
});function animate() {requestAnimationFrame(animate);if(keyStates['ArrowUp']) {robot.walk();robot.moveForward(0.1);}if(keyStates['ArrowLeft']) {robot.turn(0.05);}if(keyStates['ArrowRight']) {robot.turn(-0.05);}camera.position.x = robot.body.position.x;camera.position.z = robot.body.position.z + 10;camera.lookAt(robot.body.position);renderer.render(scene, camera);
}animate();

主要特性

  1. 3D 人形机器人模型
  2. 基本的行走动画
  3. 键盘控制系统
  4. 相机跟随
  5. 阴影效果
  6. 响应式设计

控制方法

  • ↑ 向前移动
  • ← 向左转
  • → 向右转

可能的改进方向

  1. 添加更多动作(如后退、跳跃)
  2. 改进机器人模型细节
  3. 添加碰撞检测
  4. 添加物理引擎
  5. 实现更复杂的动画效果
  6. 添加声音效果
  7. 增加更多交互控制选项
  8. 优化性能

结论

通过这个项目,我们展示了如何使用 Three.js 创建一个基本的 3D 人形机器人仿真系统。虽然这是一个相对简单的实现,但它为更复杂的 3D 网页应用提供了良好的起点。

完整代码

<!DOCTYPE html>
<html>
<head><title>3D Robot Simulation</title><style>body { margin: 0; overflow: hidden;}canvas { display: block; }#info {position: absolute;top: 10px;left: 10px;color: white;font-family: Arial;font-size: 14px;background: rgba(0,0,0,0.5);padding: 10px;}</style>
</head>
<body><div id="info">使用方向键控制机器人:<br>- 向前移动<br>← → - 左右转向</div><script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script><script>// 初始化场景、相机和渲染器const scene = new THREE.Scene();scene.background = new THREE.Color(0x87CEEB); // 天空蓝色背景const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);const renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);renderer.shadowMap.enabled = true;document.body.appendChild(renderer.domElement);// 创建机器人类class Robot {constructor() {// 机器人主体this.body = new THREE.Group();// 躯干const torsoGeometry = new THREE.BoxGeometry(2, 3, 1);const torsoMaterial = new THREE.MeshPhongMaterial({color: 0x999999});this.torso = new THREE.Mesh(torsoGeometry, torsoMaterial);this.torso.castShadow = true;// 头部const headGeometry = new THREE.SphereGeometry(0.5);const headMaterial = new THREE.MeshPhongMaterial({color: 0xcccccc});this.head = new THREE.Mesh(headGeometry, headMaterial);this.head.position.y = 2;this.head.castShadow = true;// 眼睛const eyeGeometry = new THREE.SphereGeometry(0.1);const eyeMaterial = new THREE.MeshPhongMaterial({color: 0x000000});this.leftEye = new THREE.Mesh(eyeGeometry, eyeMaterial);this.rightEye = new THREE.Mesh(eyeGeometry, eyeMaterial);this.leftEye.position.set(-0.2, 2, 0.4);this.rightEye.position.set(0.2, 2, 0.4);// 手臂this.leftArm = this.createLimb(0.3, 2);this.leftArm.position.set(-1.2, 1, 0);this.rightArm = this.createLimb(0.3, 2);this.rightArm.position.set(1.2, 1, 0);// 腿部this.leftLeg = this.createLimb(0.4, 2);this.leftLeg.position.set(-0.6, -1.5, 0);this.rightLeg = this.createLimb(0.4, 2);this.rightLeg.position.set(0.6, -1.5, 0);// 组装机器人this.body.add(this.torso);this.body.add(this.head);this.body.add(this.leftEye);this.body.add(this.rightEye);this.body.add(this.leftArm);this.body.add(this.rightArm);this.body.add(this.leftLeg);this.body.add(this.rightLeg);}createLimb(width, height) {const geometry = new THREE.BoxGeometry(width, height, width);const material = new THREE.MeshPhongMaterial({color: 0x999999});const limb = new THREE.Mesh(geometry, material);limb.castShadow = true;return limb;}walk() {// 腿部摆动const legRotation = Math.sin(Date.now() * 0.005) * 0.5;this.leftLeg.rotation.x = legRotation;this.rightLeg.rotation.x = -legRotation;// 手臂摆动const armRotation = Math.sin(Date.now() * 0.005) * 0.25;this.leftArm.rotation.x = -armRotation;this.rightArm.rotation.x = armRotation;}turn(angle) {this.body.rotation.y += angle;}moveForward(speed) {this.body.position.x += Math.sin(this.body.rotation.y) * speed;this.body.position.z += Math.cos(this.body.rotation.y) * speed;}}// 创建地面const groundGeometry = new THREE.PlaneGeometry(100, 100);const groundMaterial = new THREE.MeshPhongMaterial({ color: 0x808080,side: THREE.DoubleSide});const ground = new THREE.Mesh(groundGeometry, groundMaterial);ground.rotation.x = -Math.PI / 2;ground.position.y = -2.5;ground.receiveShadow = true;scene.add(ground);// 创建机器人实例const robot = new Robot();scene.add(robot.body);// 添加光源const directionalLight = new THREE.DirectionalLight(0xffffff, 1);directionalLight.position.set(5, 10, 5);directionalLight.castShadow = true;directionalLight.shadow.camera.near = 0.1;directionalLight.shadow.camera.far = 100;directionalLight.shadow.camera.left = -50;directionalLight.shadow.camera.right = 50;directionalLight.shadow.camera.top = 50;directionalLight.shadow.camera.bottom = -50;scene.add(directionalLight);const ambientLight = new THREE.AmbientLight(0x404040);scene.add(ambientLight);// 设置相机位置camera.position.set(0, 5, 10);camera.lookAt(robot.body.position);// 键盘状态const keyStates = {};// 键盘事件监听document.addEventListener('keydown', (e) => {keyStates[e.key] = true;});document.addEventListener('keyup', (e) => {keyStates[e.key] = false;});// 窗口大小调整window.addEventListener('resize', onWindowResize, false);function onWindowResize() {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);}// 动画循环function animate() {requestAnimationFrame(animate);// 更新机器人动作if(keyStates['ArrowUp']) {robot.walk();robot.moveForward(0.1);}if(keyStates['ArrowLeft']) {robot.turn(0.05);}if(keyStates['ArrowRight']) {robot.turn(-0.05);}// 相机跟随camera.position.x = robot.body.position.x;camera.position.z = robot.body.position.z + 10;camera.lookAt(robot.body.position);renderer.render(scene, camera);}animate();</script>
</body>
</html>

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

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

相关文章

Python大数据可视化:基于python大数据的电脑硬件推荐系统_flask+Hadoop+spider

开发语言&#xff1a;Python框架&#xff1a;flaskPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 价格区间界面 用户信息界面 品牌管理 笔记本管理 电脑主机…

修改vue-element-admin,如何连接我们的后端

改哪几个文件就可以连接我们后端 ​​​​​​​ 主要就这四个 main.js&#xff0c;屏蔽这个或者删除 vue-config 最后两个文件改下端口即可 这样基本就能发了&#xff0c;但是还要改下 改成api 然后还要修改request.js 这里改成我们返回的状态码 我讲一个东西很容易就懂了&…

uniapp实现为微信小程序扫一扫的功能

引言 随着微信小程序的快速发展,越来越多的开发者开始关注和学习微信小程序的开发。其中,微信小程序的扫一扫功能是非常常用且实用的功能之一。通过扫描二维码,用户可以获取到相关的信息或者实现特定的功能。 正文 在过去,开发者需要使用微信开发者工具以及相关的开发文档…

UE(虚幻)学习(四) 第一个C++类来控制小球移动来理解蓝图和脚本如何工作

UE5视频看了不少&#xff0c;但基本都是蓝图如何搞&#xff0c;或者改一下属性&#xff0c;理解UE系统现有组件使用的。一直对C脚本和蓝图之间的关系不是很理解&#xff0c;看到一个视频讲的很好&#xff0c;我也做笔记记录一下。 我的环境是UE5.3.2. 创建UE空项目 我们创建…

【Redis】Redis 安装与启动

在实际工作中&#xff0c;大多数企业选择基于 Linux 服务器来部署项目。本文演示如何使用 MobaXterm 远程连接工具&#xff0c;在 CentOS 7 上安装和启动 Redis 服务&#xff08;三种启动方式&#xff0c;包括默认启动、指定配置启动和开机自启&#xff09;。在安装之前&#x…

SpringCloudAlibaba实战入门之路由网关Gateway初体验(十一)

Spring Cloud 原先整合 Zuul 作为网关组件,Zuul 由 Netflix 公司提供的,现在已经不维护了。后面 Netflix 公司又出来了一个 Zuul2.0 网关,但由于一直没有发布稳定版本,所以 Spring Cloud 等不及了就自己推出一个网关,已经不打算整合 zuul2.0 了。 一、什么是网关 1、顾明…

【unity c#】深入理解string,以及不同方式构造类与反射的性能测试(基于BenchmarkDotNet)

出这篇文章的主要一个原因就是ai回答的性能差异和实际测试完全不同&#xff0c;比如说是先获取构造函数再构造比Activator.CreateInstance(type)快&#xff0c;实际却相反 对测试结果的评价基于5.0&#xff0c;因为找不到unity6确切使用的net版本&#xff0c;根据c#9推测是net5…

使用RKNN进行YOLOv8人体姿态估计的实战教程:yolov8-pose.onnx转yolov8-pose.rknn+推理全流程

之前文章有提到“YOLOv8的原生模型包含了后处理步骤,其中一些形状超出了RK3588的矩阵计算限制,因此需要对输出层进行一些裁剪”,通过裁剪后得到的onnx能够顺利的进行rknn转换,本文将对转rnkk过程,以及相应的后处理进行阐述。并在文末附上全部源码、数据、模型的百度云盘链…

C# OpenCV机器视觉:凸包检测

在一个看似平常却又暗藏玄机的午后&#xff0c;阿强正悠闲地坐在实验室里&#xff0c;翘着二郎腿&#xff0c;哼着小曲儿&#xff0c;美滋滋地品尝着手中那杯热气腾腾的咖啡&#xff0c;仿佛整个世界都与他无关。突然&#xff0c;实验室的门 “砰” 的一声被撞开&#xff0c;小…

【JavaEE进阶】@RequestMapping注解

目录 &#x1f4d5;前言 &#x1f334;项目准备 &#x1f332;建立连接 &#x1f6a9;RequestMapping注解 &#x1f6a9;RequestMapping 注解介绍 &#x1f384;RequestMapping是GET还是POST请求&#xff1f; &#x1f6a9;通过Fiddler查看 &#x1f6a9;Postman查看 …

Python 自动化 打开网站 填表登陆 例子

图样 简价&#xff1a; 简要说明这个程序的功能&#xff1a; 1. **基本功能**&#xff1a; - 自动打开网站 - 自动填写登录信息&#xff08;号、公司名称、密码&#xff09; - 显示半透明状态窗口实时提示操作进度 2. **操作流程**&#xff1a; - 打开网站后自动…

oracle怎样使用logmnr恢复误删除的数据

如果有同事误删除数据了&#xff0c;可以用logmnr挖掘归档日志&#xff0c;生成回滚sql&#xff0c;快速恢复数据&#xff0c;比用整个库的备份恢复要快得多。 一 操作步骤 1.1 创建目录 su - oracle mkdir logmnr create directory logmnr_dir as /home/oracle/logmnr; …

linux自动化一键批量检查主机端口

1、准备 我们可以使用下面命令关闭一个端口 sudo iptables -A INPUT -p tcp --dport 端口号 -j DROP我关闭的是22端口&#xff0c;各位可以关其它的或者打开其它端口测试&#xff0c;谨慎关闭22端口&#xff01;不然就会像我下面一样握手超时&#x1f62d;&#x1f62d;&…

电脑缺失libcurl.dll怎么解决?详解电脑libcurl.dll文件丢失问题

一、libcurl.dll文件丢失的原因 libcurl.dll是一个用于处理URL传输的库文件&#xff0c;广泛应用于各种基于网络的应用程序。当这个文件丢失时&#xff0c;可能会导致相关应用程序无法正常运行。以下是libcurl.dll文件丢失的一些常见原因&#xff1a; 软件安装或卸载不完整&a…

SpringBoot集成Flowable

一、工作流介绍 1、概念 通过计算机对业务流程的自动化管理。工作流是建立在业务流程的基础上&#xff0c;一个软件的系统核心根本上还是系统的业务流程&#xff0c;工作流只是协助进行业务流程管理。 解决的是&#xff1a;在多个参与者之间按照某种预定义的规则自动进行传递…

如何通过采购管理系统提升供应链协同效率?

供应链是企业运营的命脉&#xff0c;任何环节的延迟或失误都会对企业造成严重影响。在采购环节中&#xff0c;如何保证与供应商的协同效率&#xff0c;避免因信息不对称而导致的决策失误&#xff0c;是企业面临的一大挑战。采购管理系统作为数字化供应链管理的重要工具&#xf…

FFmpeg 的常用API

FFmpeg 的常用API 附录&#xff1a;FFmpeg库介绍 库介绍libavcodec音视频编解码核心库编码 (avcodec_send_frame, avcodec_receive_packet)。解码 (avcodec_send_packet, avcodec_receive_frame)。libavformat提供了音视频流的解析和封装功能&#xff0c;多种多媒体封装格式&…

为什么要在PHY芯片和RJ45网口中间加网络变压器

在PHY芯片和RJ45网口之间加入网络变压器是出于以下几个重要的考虑&#xff1a; 1. 电气隔离&#xff1a;网络变压器提供了电气隔离功能&#xff0c;有效阻断了PHY芯片与RJ45之间直流分量的直接连接。这样可以防止可能的电源冲突&#xff0c;降低系统故障的风险&#xff0c;并保…

深度学习助力股市预测:LSTM、RNN和CNN模型实战解析

作者&#xff1a;老余捞鱼 原创不易&#xff0c;转载请标明出处及原作者。 写在前面的话&#xff1a;众所周知&#xff0c;传统的股票预测模型有着各种各样的局限性。但在我的最新研究中&#xff0c;探索了一些方法来高效预测股市走势&#xff0c;即CNN、RNN和LSTM这些深度学习…

sql字段值转字段

表alertlabel中记录变字段 如何用alertlabel表得到下面数据 实现的sql语句 select a.AlertID, (select Value from alertlabel where AlertIDa.AlertID and Labelhost) as host, (select Value from alertlabel where AlertIDa.AlertID and Labeljob) as job from (select …