Three.js曲线篇 8.管道漫游
目录
创建样条曲线
创建管道
透视相机漫游
完整代码
大家不要被这个“管道漫游”这几个字所蒙骗了,学完后大家就知道这个知识点有多脏了。我也是误入歧途,好奇了一下“管道漫游”。好了,现在就给大家展示一下为啥这个只是点脏了。

我也废话少说了,带大家实现这个轨道漫游。
创建样条曲线
// 3d样条曲线const path = new THREE.CatmullRomCurve3([new THREE.Vector3(-50, 20, 90),new THREE.Vector3(-10, 40, 40),new THREE.Vector3(0, 0, 0),new THREE.Vector3(60, -60, 0),new THREE.Vector3(90, -40, 60),new THREE.Vector3(120, 30, 30),]);
穿件完样条曲线后,然后需要 TubeGeometry 来创建管道。
创建管道
// 创建管道const geometry = new THREE.TubeGeometry(path, 200, 5, 30);const texLoader = new THREE.TextureLoader();const url = new URL('../../assets/images/gd.png', import.meta.url).href;const texture = texLoader.load(url);texture.wrapS = THREE.RepeatWrapping;texture.wrapT = THREE.RepeatWrapping;const material = new THREE.MeshBasicMaterial({ map: texture, side: THREE.DoubleSide });const mesh = new THREE.Mesh(geometry, material);scene.add(mesh);
透视相机漫游
透视相机漫游,其实就是按照按照样条曲线的轨迹来设置,通过 样条曲线上的一个方法 getSpacedPoints 可以获取样条曲线上一定的点位数量,然后使用循环来设置相机的位置。
// 从曲线上等间距获取一定数量点坐标const pointsArr = path.getSpacedPoints(500);let i = 0;/* ------------------------------动画函数--------------------------------- */const animation = () => {if (i < pointsArr.length - 1) {// 相机位置设置在当前点位置camera.position.copy(pointsArr[i]);// 曲线上当前点pointsArr[i]和下一个点pointsArr[i+1]近似模拟当前点曲线切线// 设置相机观察点为当前点的下一个点,相机视线和当前点曲线切线重合camera.lookAt(pointsArr[i + 1]);camera.updateProjectionMatrix();controls.target.copy(pointsArr[i + 1]);i += 1; //调节速度} else {i = 0}controls.update();// 如果不调用,就会很卡renderer.render(scene, camera);requestAnimationFrame(animation);}animation();
这里给大家带来的知识点就是利用线条来实现相机漫游的效果。
完整代码
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'export default (domId) => {/* ------------------------------初始化三件套--------------------------------- */const dom = document.getElementById(domId);const { innerHeight, innerWidth } = windowconst scene = new THREE.Scene();const camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 1, 2000);camera.position.set(50, 50, 50);camera.lookAt(scene.position);const renderer = new THREE.WebGLRenderer({antialias: true,// 抗锯齿alpha: false,// 透明度powerPreference: 'high-performance',// 性能// logarithmicDepthBuffer: true,// 深度缓冲})renderer.shadowMap.enabled = true;// 开启阴影renderer.shadowMap.type = THREE.PCFSoftShadowMap;// 阴影类型renderer.outputEncoding = THREE.sRGBEncoding;// 输出编码renderer.toneMapping = THREE.ACESFilmicToneMapping;// 色调映射renderer.toneMappingExposure = 1;// 色调映射曝光renderer.physicallyCorrectLights = true;// 物理正确灯光renderer.setPixelRatio(window.devicePixelRatio);// 设置像素比renderer.setSize(innerWidth, innerHeight);// 设置渲染器大小dom.appendChild(renderer.domElement);// 重置大小window.addEventListener('resize', () => {const { innerHeight, innerWidth } = windowcamera.aspect = innerWidth / innerHeight;camera.updateProjectionMatrix();renderer.setSize(innerWidth, innerHeight);})/* ------------------------------初始化工具--------------------------------- */const controls = new OrbitControls(camera, renderer.domElement) // 相机轨道控制器controls.enableDamping = true // 是否开启阻尼controls.dampingFactor = 0.05// 阻尼系数controls.panSpeed = -1// 平移速度const axesHelper = new THREE.AxesHelper(10);scene.add(axesHelper);/* ------------------------------正题--------------------------------- */// 3d样条曲线const path = new THREE.CatmullRomCurve3([new THREE.Vector3(-50, 20, 90),new THREE.Vector3(-10, 40, 40),new THREE.Vector3(0, 0, 0),new THREE.Vector3(60, -60, 0),new THREE.Vector3(90, -40, 60),new THREE.Vector3(120, 30, 30),]);// 创建管道const geometry = new THREE.TubeGeometry(path, 200, 5, 30);const texLoader = new THREE.TextureLoader();const url = new URL('../../assets/images/gd.png', import.meta.url).href;const texture = texLoader.load(url);texture.wrapS = THREE.RepeatWrapping;texture.wrapT = THREE.RepeatWrapping;const material = new THREE.MeshBasicMaterial({ map: texture, side: THREE.DoubleSide });const mesh = new THREE.Mesh(geometry, material);scene.add(mesh);// 从曲线上等间距获取一定数量点坐标const pointsArr = path.getSpacedPoints(500);let i = 0;/* ------------------------------动画函数--------------------------------- */const animation = () => {if (i < pointsArr.length - 1) {// 相机位置设置在当前点位置camera.position.copy(pointsArr[i]);// 曲线上当前点pointsArr[i]和下一个点pointsArr[i+1]近似模拟当前点曲线切线// 设置相机观察点为当前点的下一个点,相机视线和当前点曲线切线重合camera.lookAt(pointsArr[i + 1]);camera.updateProjectionMatrix();controls.target.copy(pointsArr[i + 1]);i += 1; //调节速度} else {i = 0}controls.update();// 如果不调用,就会很卡renderer.render(scene, camera);requestAnimationFrame(animation);}animation();
}
最后,透露一下为啥脏。

这颜色,这个洞,这个词,总觉得怪怪的。
相关文章:
Three.js曲线篇 8.管道漫游
目录 创建样条曲线 创建管道 透视相机漫游 完整代码 大家不要被这个“管道漫游”这几个字所蒙骗了,学完后大家就知道这个知识点有多脏了。我也是误入歧途,好奇了一下“管道漫游”。好了,现在就给大家展示一下为啥这个只是点脏了。 我也废话…...
scala基础_数据类型概览
Scala 数据类型 下表列出了 Scala 支持的数据类型: 类型类别数据类型描述Scala标准库中的实际类基本类型Byte8位有符号整数,数值范围为 -128 到 127scala.Byte基本类型Short16位有符号整数,数值范围为 -32768 到 32767scala.Short基本类型I…...
【LeetCode刷题之路】622.设计循环队列
LeetCode刷题记录 🌐 我的博客主页:iiiiiankor🎯 如果你觉得我的内容对你有帮助,不妨点个赞👍、留个评论✍,或者收藏⭐,让我们一起进步!📝 专栏系列:LeetCode…...
暂停一下,给Next.js项目配置一下ESLint(Next+tailwind项目)
前提 之前开自己的GitHub项目,想着不是团队项目,偷懒没有配置eslint,后面发现还是不行。eslint的存在可以帮助我们规范代码格式,同时 ctrl s保存立即调整代码格式是真的很爽。 除此之外,团队使用eslint也是好处颇多…...
Windows系统磁盘与分区之详解(Detailed Explanation of Windows System Disks and Partitions)
Windows系统磁盘与分区知识详解 在日常使用Windows操作系统的过程中,我们常常会接触到磁盘管理,磁盘分区等操作.然而,许多人可能并不完全理解磁盘和分区的运作原理以及如何高效管理它们. 本篇文章将探讨Windows系统中关于磁盘和分区的各种知识,帮助大家更好地理解磁盘以及分区…...
顺序表的使用,对数据的增删改查
主函数: 3.c #include "3.h"//头文件调用 SqlListptr sql_cerate()//创建顺序表函数 {SqlListptr ptr(SqlListptr)malloc(sizeof(SqlList));//在堆区申请连续的空间if(NULLptr){printf("创建失败\n");return NULL;//如果没有申请成功ÿ…...
XDMA与FPGA:高效数据传输的艺术
XDMA与FPGA:高效数据传输的艺术 引言 在现代计算系统中,数据传输的效率直接影响系统的整体性能。特别是在涉及到高速数据处理的领域,如高性能计算(HPC)、实时视频处理和大数据分析等,如何高效地在主机与F…...
#思科模拟器通过服务配置保障无线网络安全Radius
演示拓扑图: 搭建拓扑时要注意: 只能连接它的Ethernet接口,不然会不通 MAC地址绑定 要求 :通过配置MAC地址过滤禁止非内部员工连接WiFi 打开无线路由器GUI界面,点开下图页面,配置路由器无线网络MAC地址过…...
浅谈Python库之pillow
一、pillow的介绍 Pillow是Python Imaging Library (PIL) 的一个分支,它是一个强大的图像处理库,用于打开、操作和保存许多不同图像文件格式。Pillow提供了广泛的文件格式支持、强大的图像处理能力和广泛的文件格式兼容性。它是PIL的一个友好的分支&…...
Android通过okhttp下载文件(本文案例 下载mp4到本地,并更新到相册)
使用步骤分为两步 第一步导入 okhttp3 依赖 第二步调用本文提供的 utils 第一步这里不做说明了,直接提供第二步复制即用 DownloadUtil 中 download 为下载文件 参数说明 这里主要看你把 destFileName 下载文件名称定义为什么后缀,比如我定义为 .mp4 下…...
计算机网络从诞生之初到至今的发展历程
前言 "上网",相信大家对这个动词已经不再陌生,网 通常指的是网络;在 2024 年的今天,网络已经渗透到了每个人的生活中,成为其不可或缺的一部分;你此时此刻在看到我的博客,就是通过网络…...
Kudu 源码编译-aarch架构 1.17.1版本
跟着官方文档编译 第一个问题:在make阶段时会报的问题: kudu/src/kudu/util/block_bloom_filter.cc:210:3: error: ‘vst1q_u32_x2’ was not declared in this scope kudu/src/kudu/util/block_bloom_filter.cc:436:5: error: ‘vst1q_u8_x2’ was no…...
SEC_ASA 第二天作业
拓扑 按照拓扑图配置 NTP,Server端为 Outside路由器,Client端为 ASA,两个设备的 NTP传输使用MD5做校验。(安全 V4 LAB考点) 提示:Outside路由器作为 Server端要配置好正确的时间和时区,ASA防…...
操作系统(5)进程
一、定义与特点 定义:进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。 特点: 动态性:进程是动态创建的,有它自身的生命周期,…...
6_Sass 选择器函数 --[CSS预处理]
Sass 提供了一系列的选择器函数,用于操作和组合CSS选择器。这些函数可以帮助你更灵活地创建样式规则,并且可以减少重复代码。以下是几个常用的选择器函数及其用法: 1. selector-append($selector1, $selector2...) selector-append($select…...
考研数学【线性代数基础box(数二)】
本文是对数学二线性代数基础进行总结,一些及极其简单的被省略了,代数的概念稀碎,不如高数关联性高,所以本文仅供参考,做题请从中筛选! 本文为初稿,后面会根据刷题和自己的理解继续更新 第一章…...
ModbusTcp获取数据
ModbusTcp获取数据 记录一个用 pymodbus 库来获取数据的代码。 注意: 1.读取寄存器地址是16进制的。2.大小端转换通过代码知道原理。读取数据时,切记频率别太高,否则会出现连接被关闭问题。 from pymodbus.client.sync import ModbusTcpCli…...
java 知识点:注解及使用
注解 大多数时候,我们会使用注解,而不是自定义注解。注解给谁用?编译器 、给解析程序用注解不是程序的一部分,可以理解为注解就是一个标签 主要的作用有以下四方面: 生成文档,通过代码里标识的元数据生成…...
AI预测体彩排3采取888=3策略+和值012路+胆码+通杀1码测试12月13日升级新模型预测第156弹
经过100多期的测试,当然有很多彩友也一直在观察我每天发的预测结果,得到了一个非常有价值的信息,那就是9码定位的命中率非常高,已到达90%的命中率,这给喜欢打私菜的朋友提供了极高价值的预测结果~当然了,大…...
faiss数据库检索不稳定
faiss数据检索不稳定 def build_faiss_index(embeddings_vector):dim np.shape(embeddings_vector)[-1]index faiss.index_factory(dim, HNSW64, faiss.METRIC_INNER_PRODUCT)index.add(embeddings_vector)return index这个代码不稳定,构建的索引召回结果可能会不…...
ARM Cortex-M4嵌入式开发实战:内存管理与性能优化全解析
1. 项目概述:为什么M4的性能与内存管理值得深究如果你从经典的AVR平台(比如Arduino Uno)转向基于ARM Cortex-M4的板子(比如Adafruit的Feather M4 Express或Arduino Zero),最初的体验可能是“性能过剩”。毕…...
【Unity3D】从Cubemap到Skybox:打造沉浸式3D场景的完整实践
1. 理解Cubemap与Skybox的核心概念 第一次接触Unity3D的环境渲染时,我被那些看似无限延伸的天空和云层效果震撼了。后来才知道,这种沉浸感的核心技术就是Cubemap和Skybox的组合应用。简单来说,Cubemap就像是一个立方体盒子,六个面…...
客户端命令行
1. ./tongzkCli.sh -server 10.10.83.95:2181ls /一创建永久节点 2.创建节点并写入数据 [tongzk: 10.10.83.95:2181(CONNECTED) 2] create /jiedian1 "a1" Created /jiedian1 [tongzk: 10.10.83.95:2181(CONNECTED) 3] ls / [jiedian1, tongzk] [tongzk: 10.10.83.95…...
大模型产品经理进阶指南:从零基础到行业精英的完整学习路线图!
随着人工智能技术的发展,尤其是大模型(Large Model)的兴起,越来越多的企业开始重视这一领域的投入。作为大模型产品经理,你需要具备一系列跨学科的知识和技能,以便有效地推动产品的开发、优化和市场化。以下…...
Vue项目打印凭证纸保姆级教程:用JS动态注入@media print样式,告别全局污染
Vue项目动态打印方案实战:精准控制凭证纸与A4布局的JS样式注入技术 在财务系统和ERP开发中,打印功能往往是最容易被忽视却最影响用户体验的环节。传统Vue项目中直接使用media print会遇到一个致命问题——当同一个页面需要支持A4报表和76mm130mm凭证纸两…...
辐射4正式版.144G终极整合!含实验室355个绅士MOD.2026最新版免费下载(看到请立即转存 资源随时失效)pc手机通用
下载链接 在淘宝买160元 在游戏界,如果要选出一个“因玩家的无限创造力而获得第二次生命”的典范,Bethesda(B社)旗下的《辐射4》(Fallout 4)绝对名列前茅。尤其是被社区戏称…...
从草图到精确模型:CAD_Sketcher如何重新定义Blender参数化设计工作流
从草图到精确模型:CAD_Sketcher如何重新定义Blender参数化设计工作流 【免费下载链接】CAD_Sketcher Constraint-based geometry sketcher for blender 项目地址: https://gitcode.com/gh_mirrors/ca/CAD_Sketcher 想象一下这样的场景:你正在Blen…...
揭秘Midjourney V6 Sand印相渲染逻辑:3大隐式提示词权重公式+27组实测LORA组合效果对比
更多请点击: https://intelliparadigm.com 第一章:Midjourney V6 Sand印相的技术定位与演进脉络 Midjourney V6 的 Sand 印相(Sand Toning)并非传统暗房工艺的简单复刻,而是一种融合神经渲染、材质感知建模与跨模态风…...
Spring Framework(DI)
1.依赖注入思考:向一个类中传递数据的方式有几种?普通方法(set方法)构造方法思考:依赖注入描述了在容器中建立bean与bean之间依赖关系的过程,如果bean运行需要的是数字或字符串呢?引用类型简单类型(基本数据…...
STM32硬件SPI资源不足?混合驱动方案实现精准时序扩展
1. 项目概述:当硬件SPI口不够用时,我们怎么办?在嵌入式开发,尤其是基于STM32这类MCU的项目里,SPI(串行外设接口)是连接各类传感器、存储芯片、显示屏的绝对主力。但STM32的型号繁多,…...
