ThreeJS-战争导弹飞行演示(三十四)
关键代码:
function animate() {
requestAnimationFrame(animate);
// 使用渲染器渲染相机看这个场景的内容渲染出来
renderer.render(scene, camera);
// controls.update();
// 获取delay时间
const delay = clock.getDelta();
// 获取总共耗时
const time = clock.getElapsedTime();
console.log("总耗时", time)
let t = time % 5;
t /= 5;
// console.log(t);
// 通过curvePath获取曲线上的点
if (curvePath) {
const point = curvePath.getPointAt(t);
// console.log(point);
// 通过point设置模型dd位置
// 获取点的切线
const tangent = curvePath.getTangentAt(t);
dd.position.set(point.x, point.y, point.z);
// 设置模型的朝向
if (t + 0.01 < 1) {
const point1 = curvePath.getPointAt(t + 0.01);
// console.log(point1);
dd.lookAt(point1);
}
// oldPoint = point;
// dd.lookAt(tangent);
if (t > 0.95) {
scene.add(sprite);
// 判断声音是否播放,如果没有播放则播放
if (!sound.isPlaying) {
sound.play();
}
}
}
params.iTime.value = t * 10;
// if (mixer) {
// mixer.update(delay);
// }
}
完整代码:
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
import { DRACOLoader } from "three/examples/jsm/loaders/dracoloader";
import * as dat from "dat.gui";
import vertexShader from "../shader/vertexShader.glsl";
import fragmentShader from "../shader/fragmentShader.glsl";
import { SpriteMaterial } from "three";
//创建gui对象
const gui = new dat.GUI();
// 目标:了解threejs基础内容
// console.log(THREE);
// 初始化场景
const scene = new THREE.Scene();
// 添加辅助坐标轴
// const axesHelper = new THREE.AxesHelper(20);
// scene.add(axesHelper);
// 创建透视相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerHeight / window.innerHeight,
0.1,
1000
);
// 设置相机位置
camera.position.set(0, 5, 10);
scene.add(camera);
// const rgbeLoader = new RGBELoader().setPath("assets/");
let mixer, dd, els, wkl, path;
// rgbeLoader.loadAsync("kloppenheim_02_2k.hdr").then((texture) => {
// texture.mapping = THREE.EquirectangularReflectionMapping;
// // console.log(texture);
// scene.background = texture;
// scene.environment = texture;
// });
// 使用dracoloader载入draco格式的模型
const dracoLoader = new DRACOLoader();
// 载入ew.glb模型
const loader = new GLTFLoader();
let curvePath;
loader.load("assets/ew8.glb", (gltf) => {
console.log(gltf);
gltf.scene.traverse((child) => {
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
}
});
//俄罗斯
els = gltf.scene.children[0];
//路线
path = gltf.scene.children[2];
//乌克兰
wkl = gltf.scene.children[1];
//导弹
dd = gltf.scene.children[3];
scene.add(els, wkl, dd);
// 根据点创建曲线
const points = [];
for (let i = path.geometry.attributes.position.count - 1; i >= 0; i--) {
points.push(
new THREE.Vector3(
path.geometry.attributes.position.array[i * 3],
path.geometry.attributes.position.array[i * 3 + 1],
path.geometry.attributes.position.array[i * 3 + 2]
)
);
}
curvePath = new THREE.CatmullRomCurve3(points);
console.log("弧长", curvePath.getLength())
// 设置载入的所有物体接收和投射阴影
// 调用mixer控制动画
// mixer = new THREE.AnimationMixer(dd);
// const action = mixer.clipAction(gltf.animations[0]);
// action.play();
});
// dracoLoader.preload();
// dracoLoader.load("assets/ew.glb", (gltf) => {
// console.log(gltf);
// // scene.add(gltf.scene);
// });
// 环境光;
const ambientLight = new THREE.AmbientLight(0xffffff, 1);
scene.add(ambientLight);
// 添加平行光源
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(1, 10, 1);
directionalLight.castShadow = true;
scene.add(directionalLight);
// 添加另外一个平行光源
const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight2.position.set(-1, -1, -1);
directionalLight2.castShadow = true;
scene.add(directionalLight2);
// 创建平面添加到场景中
const planeGeometry = new THREE.PlaneGeometry(2, 2);
// 设置shader材质
const planeMaterial = new THREE.ShaderMaterial({
uniforms: {
iResolution: {
value: new THREE.Vector2(window.innerWidth, window.innerHeight),
// value: new THREE.Vector2(800, 800),
},
iTime: {
value: 0,
},
iChannel0: {
value: new THREE.TextureLoader().load("assets/ichannel0.png"),
},
iChannel1: {
value: new THREE.TextureLoader().load("assets/ichannel1.png"),
},
iChannel2: {
value: new THREE.TextureLoader().load("assets/ichannel2.png"),
},
iMouse: {
value: new THREE.Vector2(0, 0),
},
},
vertexShader: vertexShader,
fragmentShader: fragmentShader,
transparent: true,
blending: THREE.AdditiveBlending,
side: THREE.DoubleSide,
});
// 添加平面到场景
// const plane = new THREE.Mesh(planeGeometry, planeMaterial);
// scene.add(plane);
// 添加sprite
// 创建精灵材质
const params = {
iTime: {
value: 0,
},
};
const spriteMaterial = new SpriteMaterial({
color: 0xffffff,
blending: THREE.AdditiveBlending,
});
spriteMaterial.onBeforeCompile = (shader) => {
shader.uniforms.iResolution = {
value: new THREE.Vector2(window.innerWidth, window.innerHeight),
};
shader.uniforms.iTime = params.iTime;
shader.uniforms.iChannel0 = {
value: new THREE.TextureLoader().load("assets/ichannel0.png"),
};
shader.uniforms.iChannel1 = {
value: new THREE.TextureLoader().load("assets/ichannel1.png"),
};
shader.uniforms.iChannel2 = {
value: new THREE.TextureLoader().load("assets/ichannel2.png"),
};
shader.uniforms.iMouse = { value: new THREE.Vector2(0, 0) };
console.log(shader.vertexShader);
shader.vertexShader = shader.vertexShader.replace(
"#include <common>",
`
#include <common>
varying vec2 vUv;
`
);
shader.vertexShader = shader.vertexShader.replace(
"#include <uv_vertex>",
`
#include <uv_vertex>
vUv = uv;
`
);
shader.fragmentShader = fragmentShader;
};
// const sprite = new THREE.Sprite(planeMaterial);
const sprite = new THREE.Sprite(spriteMaterial);
sprite.position.set(-5.5, 0.8, 0);
// scene.add(sprite);
// 添加一个球到场景
// const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
// const sphere = new THREE.Mesh(sphereGeometry, planeMaterial);
// scene.add(sphere);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1;
// 设置渲染器阴影
renderer.shadowMap.enabled = true;
// 设置渲染尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将渲染器添加到body
document.body.appendChild(renderer.domElement);
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
// 设置渲染器的像素比例
renderer.setPixelRatio(window.devicePixelRatio);
// 初始化控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
controls.autoRotateSpeed = 0.5;
// 添加声音
const listener = new THREE.AudioListener();
const sound = new THREE.Audio(listener);
const audioLoader = new THREE.AudioLoader();
audioLoader.load("assets/bomb.mp3", (buffer) => {
sound.setBuffer(buffer);
// sound.setLoop(true);
sound.setVolume(0.5);
// sound.play();
});
// 创建clock
const clock = new THREE.Clock();
let oldPoint;
// 设置渲染函数
function animate() {
requestAnimationFrame(animate);
// 使用渲染器渲染相机看这个场景的内容渲染出来
renderer.render(scene, camera);
// controls.update();
// 获取delay时间
const delay = clock.getDelta();
// 获取总共耗时
const time = clock.getElapsedTime();
console.log("总耗时", time)
let t = time % 5;
t /= 5;
// console.log(t);
// 通过curvePath获取曲线上的点
if (curvePath) {
const point = curvePath.getPointAt(t);
// console.log(point);
// 通过point设置模型dd位置
// 获取点的切线
const tangent = curvePath.getTangentAt(t);
dd.position.set(point.x, point.y, point.z);
// 设置模型的朝向
if (t + 0.01 < 1) {
const point1 = curvePath.getPointAt(t + 0.01);
// console.log(point1);
dd.lookAt(point1);
}
// oldPoint = point;
// dd.lookAt(tangent);
if (t > 0.95) {
scene.add(sprite);
// 判断声音是否播放,如果没有播放则播放
if (!sound.isPlaying) {
sound.play();
}
}
}
params.iTime.value = t * 10;
// if (mixer) {
// mixer.update(delay);
// }
}
animate();
// 监听屏幕大小改变的变化,设置渲染的尺寸
window.addEventListener("resize", () => {
// console.log("resize");
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
// 设置渲染器的像素比例
renderer.setPixelRatio(window.devicePixelRatio);
});
效果图:
相关文章:
ThreeJS-战争导弹飞行演示(三十四)
关键代码: function animate() { requestAnimationFrame(animate); // 使用渲染器渲染相机看这个场景的内容渲染出来 renderer.render(scene, camera); // controls.update(); // 获取delay时间 const delay clock.getDelta(); // 获取总共耗时 const time clock.…...
代码随想录_226翻转二叉树、101对称二叉树
leetcode 226. 翻转二叉树 226. 翻转二叉树 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例 1: 输入:root [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1]示例 2: 输入:r…...
Docker 容器日志查看
1、容器日志查看命令 Usage: docker logs [OPTIONS] CONTAINERFetch the logs of a containerOptions:--details Show extra details provided to logs-f, --follow Follow log output--since string Show logs since timestamp (e.g. 2013-01-02T13:23:37Z…...
【Maven】1—Maven概述下载配置
⭐⭐⭐⭐⭐⭐ Github主页👉https://github.com/A-BigTree 笔记链接👉https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以,麻烦各位看官顺手点个star~😊 如果文章对你有所帮助,可以点赞👍…...
【Spark】RDD缓存机制
1. RDD缓存机制是什么? 把RDD的数据缓存起来,其他job可以从缓存中获取RDD数据而无需重复加工。 2. 如何对RDD进行缓存? 有两种方式,分别调用RDD的两个方法:persist 或 cache。 注意:调用这两个方法后并不…...
学成在线:第六天(p94-p102)
1、面试:为什么要用 Freemarker 静态化?如何做的? 页面静态化是指使用模板引擎技术将一个动态网页生成 html 静态页面。 满足下边的条件可以考虑使用静态化: 1、该页面被访问频率高,比如:商品信息展示、专家介绍页面等…...
读懂AUTOSAR:PduR模块--使用FIFO
简介: 现在的汽车越来越智能化和复杂化,这得益于汽车软件和电子控制系统的发展。为了帮助汽车制造商和供应商更好地开发和管理汽车软件,全球性的汽车软件开发标准——AUTOSAR(AUTomotive Open System ARchitecture)应…...
对象的比较(数据结构系列12)
目录 前言: 1.PriorityQueue 1.1PriorityQueue的特性 1.2PriorityQueue的构造器 1.3大根堆的创建 1.4PriorityQueue中函数的说明 2.java中对象的比较 2.1基本类型的比较 2.2对象的比较 2.2.1覆写基类的equals 2.2.2基于Comparable接口类的比较 2.2.3基于…...
31.下一个排列
1. 题目 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如,arr [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地&…...
ToBeWritten之理解嵌入式Web HTTP协议
也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 转移发布平台通知:将不再在CSDN博客发布新文章,敬…...
顶级程序员的成长之路1
本文关注的问题是程序员的水平究竟应该按照什么样的不同层级而逐渐提高?或者说,在学习编程的过程中,每一个阶段究竟应当设定什么样的目标才比较合理?本文的内容主要借鉴了周伟明先生的专栏文章《程序员的十层楼》[86]。注意本文讨…...
第三代api自动化测试框架使用教程(pytest+allure+sql+yaml)
使用教程一、配置1、环境配置2、框架配置3、启动入口二、用例编写1、用例模板2、参数依赖写法2、函数(方法插件)写法3、接口上传文件和表单参数4、接口上传json参数5、接口无数据填写6、code断言7、body断言7、json断言8、sql断言9、完整断言写法&#x…...
Qt——实现一个获取本机网络信息的界面
效果展现 代码实现 networkinformation.h: #ifndef NETWORKINFORMATION_H #define NETWORKINFORMATION_H#include <QMainWindow> #include <QLabel> #include <QLineEdit> #include <QPushButton>class NetworkInformation : public QMai…...
全面深入了解接口自动化,看完还不会我报地址
一、自动化分类 (1)接口自动化 python/javarequestsunittest框架来实现 python/javaRF(RobotFramework)框架来实现——对于编程要求不高 (2)Web UI功能自动化 python/javaseleniumunittestddtPO框架来实…...
Python 小型项目大全 61~65
六十一、ROT13 密码 原文:http://inventwithpython.com/bigbookpython/project61.html ROT13 密码是最简单的加密算法之一,代表“旋转 13 个空格”密码将字母A到Z表示为数字 0 到 25,加密后的字母距离明文字母 13 个空格: A变成N&…...
Hlog
Hlog 简介 Hlog是Hbase实现WAL(Write ahead log )方式产生的日志信息 , 内部是一个简单的顺序日志。每个RegionServer对应1个Hlog(备注:1.X版本的可以开启MultiWAL功能,允许对应多个Hlog),所有对于该RegionServer的写入都会被记录到Hlog中。H…...
学编程应该选择什么操作系统?
今天来聊一个老生常谈的问题,学编程时到底选择什么操作系统?Mac、Windows,还是别的什么。。 作为一个每种操作系统都用过很多年的程序员,我会结合我自己的经历来给大家一些参考和建议。 接下来先分别聊聊每种操作系统的优点和不…...
Oracle基础部分二(伪列/表、单个函数、空值处理、行列转换、分析函数、集合运算)
Oracle基础部分二(伪列/表、单个函数、空值处理、行列转换、分析函数、集合运算)1 伪列、伪表1.1 伪列1.2 伪表2 单个函数2.1 常用字符串函数2.1.1 length() 询指定字符的长度2.1.2 substr() 用于截取字符串2.1.3 concat() 用于字符串拼接2.2 常用数值函…...
c/c++:原码,反码,补码和常见的数据类型取值范围,溢出
c/c:原码,反码,补码和常见的数据类型取值范围,溢出 2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,此时学会c的话, 我所知道的周边的会c的同学,可手握…...
Java题目训练——年终奖和迷宫问题
目录 一、年终奖 二、迷宫问题 一、年终奖 题目描述: 小东所在公司要发年终奖,而小东恰好获得了最高福利,他要在公司年会上参与一个抽奖游戏,游戏在一个6*6的棋盘上进行,上面放着36个价值不等的礼物, 每…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...
macOS 终端智能代理检测
🧠 终端智能代理检测:自动判断是否需要设置代理访问 GitHub 在开发中,使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新,例如: fatal: unable to access https://github.com/ohmyzsh/oh…...
