Threejs用下个点方法实现模型沿着轨道行驶

        上一文中实现了用模型所在点的切线方式确定模型的朝向,这个章节是对上个章节的补充,用一种更简单的方式实现小车沿着轨道方向移动,如上文前半部分内容,需要创建场景,轨道,加载车的模型,一切就绪。

        threejs中有lookAt方法,这个方法不止是针对相机,也可以用于模型让模型对着某个点,因此让小车时刻对着轨迹的方向,只需要获取到小车所在为止的下一个点,并让小车始终把车头对着自己要去的那个点,就可以实现方向的控制。

  if (this.pathIndex === 999) {this.pathIndex = 0;}else{this.pathIndex += 1;}if (this.agv) {// 判断agv加载完成后,开始不断更新agv的位置let beginPoint = this.pathPoints[this.pathIndex]this.agv.position.set( beginPoint.x, beginPoint.y, beginPoint.z);//设置新的agv位置let endPoint = this.pathPoints[this.pathIndex+1];//获取小车下一个点的位置this.agv.lookAt(endPoint);//设置agv的模型朝向为切线的方向}

不过需要注意的是,在做循环执行的时候,不能判断小车是否走到最后一个点,因为小车走到最后一个点的时候,下一个点是不存在的,所以应该判断小车是否走到倒数第二个点,当小车走到倒数第二个点的时候就要让点的下标重置。否则会发生数组越界。因此上面要判断等于999就重置为0,

下面是全部的源码:

<template><div><div id="container"></div></div>
</template><script>
import * as THREE from 'three'
import {OrbitControls} from "three/addons/controls/OrbitControls";
import {GLTFLoader} from "three/addons/loaders/GLTFLoader";let scene;
export default {name: "agv-single",data() {return{camera:null,cameraCurve:null,renderer:null,container:null,controls:null,pathIndex:0,//小车的运动轨迹点索引agv:null,pathPoints:[],}},methods:{initScene(){scene = new THREE.Scene();},initCamera(){this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);this.camera.position.set(500,500,500);},initLight(){//添加两个平行光const directionalLight1 = new THREE.DirectionalLight(0xffffff, 1.5);directionalLight1.position.set(-300,-300,600)scene.add(directionalLight1);const directionalLight2 = new THREE.DirectionalLight(0xffffff, 1.5);directionalLight2.position.set(600,200,600)scene.add(directionalLight2);},initRound(){//通过CatmullRomCurve3连接4个点绘制一条曲线,且闭合this.cameraCurve = new THREE.CatmullRomCurve3([new THREE.Vector3(-300, 40, 200),new THREE.Vector3(300, 40, 200),new THREE.Vector3(300, 40, -200),new THREE.Vector3(-300, 40, -200),],true);//参考路径上取1000个点,每个点上添加蓝色小球this.pathPoints = this.cameraCurve.getPoints(1000);//绘制一条路径参考线与上面的线重合,方便查看小车的行动轨迹const geometry = new THREE.BufferGeometry().setFromPoints(this.pathPoints);const material = new THREE.LineBasicMaterial({ color: '#000000', linewidth: 1, });//设置线条的颜色和宽度const curveObject = new THREE.Line(geometry, material);scene.add(curveObject);//在场景中加载一个agv小车,并将agv小车放在曲线的第一个点上const loader = new GLTFLoader()loader.load("/static/model/agv.gltf", (gltf) => {this.agv = gltf.scene;this.agv.position.set(this.pathPoints[0].x, this.pathPoints[0].y, this.pathPoints[0].z)   // 模型位置this.agv.scale.set(0.1,0.1,0.1)scene.add(this.agv)   // 加入场景})},initRenderer(){this.renderer = new THREE.WebGLRenderer({ antialias: true });this.container = document.getElementById("container")this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);this.renderer.setClearColor('#AAAAAA', 1.0);this.container.appendChild(this.renderer.domElement);},initControl(){this.controls = new OrbitControls(this.camera, this.renderer.domElement);this.controls.enableDamping = true;this.controls.maxPolarAngle = Math.PI / 2.2;      // // 最大角度},initAnimate() {//参考路径的索引在1001~0中往复减少以实现小车循环行驶if (this.pathIndex === 999) {this.pathIndex = 0;}else{this.pathIndex += 1;}if (this.agv) {// 判断agv加载完成后,开始不断更新agv的位置let beginPoint = this.pathPoints[this.pathIndex]this.agv.position.set( beginPoint.x, beginPoint.y, beginPoint.z);//设置新的agv位置let endPoint = this.pathPoints[this.pathIndex+1];//获取小车下一个点的位置this.agv.lookAt(endPoint);//设置agv的模型朝向为切线的方向}requestAnimationFrame(this.initAnimate);this.renderer.render(scene, this.camera);},initPage(){this.initScene();this.initCamera();this.initLight();this.initRenderer();this.initControl();this.initRound();this.initAnimate();}},mounted() {this.initPage()}
}
</script><style scoped>
#container{position: absolute;width:100%;height:100%;overflow: hidden;
}</style>

效果图如下

模型沿着曲线运动

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

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

相关文章

mac 配置.bash_profile不生效问题

1、问题描述 mac系统中配置了环境变量只能在当前终端生效&#xff0c;切换了终端就无效了&#xff0c;查了下问题所在。mac系统会预装一个终极shell - zsh&#xff0c;环境变量读取在 .zshrc 文件下。 2、解决方案 1、切换终端到bash 切换终端到bash chsh -s /bin/bash 切换终端…

【随笔】程序员的金三银四求职宝典,每个人都有最合适自己的求职宝典

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读文章&#xff01; 此篇是【话题达人】系列文章&#xff0c;这一次的话题是《程序员的金三银四求职宝典》 目录 背景能力流程图求职宝典就业数据人数曲线图增长率柱状图 其他建议文章推荐 背景 随着春天的脚步渐近&#xff0…

【JavaEE初阶】 关于JVM垃圾回收

文章目录 &#x1f343;前言&#x1f38b;死亡对象的判断算法&#x1f6a9;引用计数算法&#x1f6a9;可达性分析算法 &#x1f333;垃圾回收算法&#x1f6a9;标记-清除算法&#x1f6a9;复制算法&#x1f6a9;标记-整理算法&#x1f6a9;分代算法&#x1f388;哪些对象会进入…

Redis与 Memcache区别

Redis与 Memcache区别 1 , Redis 和 Memcache 都是将数据存放在内存中&#xff0c;都是内存数据库。不过 Memcache 还可用于缓存 其他东西&#xff0c;例如图片、视频等等。 2 , Memcache 仅支持key-value结构的数据类型&#xff0c;Redis不仅仅支持简单的key-value类型的数据&…

STM32 | Proteus 8.6安装步骤(图文并茂)

01 Proteus 8.6 简介 Proteus 8.6 是一款功能强大的电子设计自动化软件&#xff0c;广泛用于电路设计、仿真和PCB布局。它为电子工程师和学生提供了一个全面的工具集&#xff0c;用于设计和验证各种电路和电子设备。Proteus 8.6 包括了以下几个主要特性&#xff1a; 1. 电路设…

低代码与微服务:重塑软件开发的未来

在软件开发的浩瀚宇宙中&#xff0c;新的技术和理念不断涌现&#xff0c;为开发者提供了更为广阔的创新空间。其中&#xff0c;“低代码”与“微服务”无疑是两颗璀璨的明星&#xff0c;它们正在改变着传统的软件开发模式&#xff0c;为开发者带来了更高效、更灵活的开发体验。…

Java实战:Spring Boot+Netty+Websocket实现后台向前端推送信息

本文将详细介绍如何使用Spring Boot集成Netty和Websocket&#xff0c;实现后台向前端推送信息的功能。我们将深入探讨Netty和Websocket的原理&#xff0c;以及如何利用Spring Boot简化Netty的集成和配置。 1. 引言 在当今的互联网应用中&#xff0c;实时通信变得越来越重要。…

力扣404. 左叶子之和(java)

//当前节点的左子树不为空 且是叶子节点 root.left ! null &&root.left.leftnull && root.left.rightnull/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* …

git分布式管理-头歌实验搭建Git服务器

一、Git服务器搭建 任务描述 虽然有提供托管代码服务的公共平台&#xff0c;但是对一部分开发团队来说&#xff0c;为了不泄露项目源代码、节省费用及为项目提供更好的安全保护&#xff0c;往往需要搭建私有Git服务器用做远程仓库。Git服务器为团队的开发者们&#xff0c;提供了…

洛谷 P8816 [CSP-J 2022] 上升点列(T4)

目录 题目传送门 算法解析 最终代码 提交结果 尾声 题目传送门 [CSP-J 2022] 上升点列 - 洛谷https://www.luogu.com.cn/problem/P8816 算法解析 k 0 且 xi, yi 值域不大时&#xff0c;这题是非常简单的 DP&#xff0c;类似「数字三角形」。 记 dp(x,y) 为「以 (x,y) …

Spring中SmartInitializingSingleton、SmartLifecycle和Lifecycle的作用和区别

相同点&#xff1a; ​ SmartInitializingSingleton和Lifecycle、SmartLifecycle都是在所有的单实例bean创建(getBean方法)之后执行。 不同点&#xff1a; SmartInitializingSingleton优先于Lifecycle、SmartLifecycle执行。SmartInitializingSingleton只有一个afterSinglet…

tomcat基础介绍

目录 一、Tomcat的基本介绍 1、Tomcat是什么&#xff1f; 2、Tomcat的配置文件详解 3、Tomcat的构成组件 6、Tomcat的请求过程 一、Tomcat的基本介绍 1、Tomcat是什么&#xff1f; Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器…

svg图标转组件引入项目中

svg图标转组件引入项目中 您想知道关于 的更多信息吗? 并不是一个特定的 HTML 元素,它更可能是一个占位符,代表一个在 Vue.js 中的动态组件。 在 Vue.js 中,动态组件可以根据不同的数据或状态加载不同的组件。 元素通常用于在模板中声明动态组件的占位符。具体来说,你可…

[leetcode 189][轮转数组]

[leetcode 189][轮转数组] 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右…

【深度学习|图像分割】读取并修改xml中的指定参数

读取并修改xml中的指定参数 1、背景2、代码 1、背景 <?xml version"1.0" ?><net name"Model4" version"11"><layers><layer id"0" name"args" type"Parameter" version"opset1"…

蓝桥集训之火柴排队

蓝桥集训之火柴排队 核心思想&#xff1a;离散化归并排序 由于数据范围较小10w 需要控制时间复杂度到nlogn 同时排两个数组会超时所以将a数组离散化成顺序数组 b数组离散化后再归并排序求逆序对数量 #include<iostream>#include <algorithm>#include <cstrin…

植物病虫害:YOLO玉米病虫害识别数据集

玉米病虫害识别数据集&#xff1a;玉米枯萎病&#xff0c;玉米灰斑病&#xff0c;玉米锈病叶&#xff0c;粘虫幼虫&#xff0c;玉米条斑病&#xff0c;黄二化螟&#xff0c;黄二化螟幼虫7类&#xff0c;yolo标注完整&#xff0c;3900多张图像&#xff0c;全部原始数据&#xff…

二、TensorFlow结构分析(4)

TF数据流图图与TensorBoard会话张量Tensor变量OP高级API 目录 1、变量 2、高级API 1、变量 2、高级API

RFID技术进阶:频段选择的艺术与科学

RFID技术进阶&#xff1a;频段选择的艺术与科学 在数字化、自动化的浪潮中&#xff0c;RFID&#xff08;无线射频识别&#xff09;技术以其独特的优势&#xff0c;逐渐在多个领域占据了一席之地。RFID&#xff08;Radio Frequency Identification&#xff09;&#xff0c;即无…

24/03/07总结

esayx: 贪吃蛇: #include "iostream" #include "cmath" #include "conio.h" #include "easyx.h" #include "time.h" #define NODE_WIDTH 40 using namespace std; typedef struct {int x;int y; }node; enum direction /…