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个价值不等的礼物, 每…...
MemoryOS:开源时序知识图谱AI记忆系统
AI的记忆困局:为什么需要"时序"和"知识图谱"?用过ChatGPT或任何AI助手的人大概都有过这样的体验:昨天告诉AI自己住在北京,今天问它"我住哪儿",它可能还能答对;但是过了两周&…...
JUCE框架移植MDA经典音频插件:从VST2到现代跨平台开发实践
1. 项目概述:JUCE框架下的MDA插件遗产如果你在音频插件开发领域摸爬滚打过一段时间,尤其是对开源社区有所关注,那么“mda-plugins-juce”这个名字大概率会唤起你的一些记忆。这个由hollance维护的GitHub仓库,本质上是一个“移植”…...
XHS-Downloader终极指南:如何高效批量下载小红书内容
XHS-Downloader终极指南:如何高效批量下载小红书内容 【免费下载链接】XHS-Downloader 小红书(XiaoHongShu、RedNote)链接提取/作品采集工具:提取账号发布、收藏、点赞、专辑作品链接;提取搜索结果作品、用户链接&…...
Snipe-IT终极指南:如何构建企业级IT资产管理系统
Snipe-IT终极指南:如何构建企业级IT资产管理系统 【免费下载链接】snipe-it A free open source IT asset/license management system 项目地址: https://gitcode.com/GitHub_Trending/sn/snipe-it 在当今数字化时代,企业IT资产管理已成为组织运营…...
AI技能实战指南:从提示工程到RAG与LoRA微调全流程解析
1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的仓库,叫tqviet1978/ai-skills。光看名字,你可能会觉得这又是一个关于“AI技能”的泛泛而谈的教程合集。但点进去仔细研究后,我发现它的定位非常精准,更像是一个为开发者、技…...
告别Spoon客户端!手把手教你用这个Vue+SpringCloud的Kettle Web版开源工具
从桌面到云端:基于VueSpringCloud的Kettle Web化实践指南 对于长期使用Kettle Spoon客户端的ETL工程师而言,反复安装Java环境、处理客户端兼容性问题、在多台机器间同步配置已成为日常痛点。当团队需要协作开发或管理远程服务器上的数据集成任务时&…...
Python try...except ImportError 语句详解
在Python编程中,ImportError 是与模块导入相关的核心异常。优雅地处理它,是编写健壮、可维护和跨平台代码的关键。try...except ImportError 结构正是实现这一目标的标准工具。本文将为你抽丝剥茧,从基础概念到高级实践,全面解析这…...
AI智能体编排平台:从任务自动化到生态协作的架构与实践
1. 项目概述:一个面向AI编排与技能提升的生态协作平台最近在和一些做AI应用开发的朋友聊天,大家普遍有个痛点:现在AI工具和模型太多了,从大语言模型到图像生成,再到各种自动化脚本,每个都很强大,…...
AI智能体生态的包管理器:agenticmarket-cli 设计与实践
1. 项目概述:一个面向AI智能体生态的命令行工具如果你和我一样,长期在AI智能体(Agent)这个领域里折腾,那你肯定经历过这样的场景:为了测试一个最新的开源智能体框架,你需要先找到它的GitHub仓库…...
AICoverGen终极指南:5分钟用AI制作专业级翻唱歌曲
AICoverGen终极指南:5分钟用AI制作专业级翻唱歌曲 【免费下载链接】AICoverGen A WebUI to create song covers with any RVC v2 trained AI voice from YouTube videos or audio files. 项目地址: https://gitcode.com/gh_mirrors/ai/AICoverGen 想不想让AI…...
