当前位置: 首页 > news >正文

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-战争导弹飞行演示(三十四)

关键代码&#xff1a; function animate() { requestAnimationFrame(animate); // 使用渲染器渲染相机看这个场景的内容渲染出来 renderer.render(scene, camera); // controls.update(); // 获取delay时间 const delay clock.getDelta(); // 获取总共耗时 const time clock.…...

代码随想录_226翻转二叉树、101对称二叉树

leetcode 226. 翻转二叉树 ​​​226. 翻转二叉树 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a;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主页&#x1f449;https://github.com/A-BigTree 笔记链接&#x1f449;https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以&#xff0c;麻烦各位看官顺手点个star~&#x1f60a; 如果文章对你有所帮助&#xff0c;可以点赞&#x1f44d;…...

【Spark】RDD缓存机制

1. RDD缓存机制是什么&#xff1f; 把RDD的数据缓存起来&#xff0c;其他job可以从缓存中获取RDD数据而无需重复加工。 2. 如何对RDD进行缓存&#xff1f; 有两种方式&#xff0c;分别调用RDD的两个方法&#xff1a;persist 或 cache。 注意&#xff1a;调用这两个方法后并不…...

学成在线:第六天(p94-p102)

1、面试&#xff1a;为什么要用 Freemarker 静态化?如何做的&#xff1f; 页面静态化是指使用模板引擎技术将一个动态网页生成 html 静态页面。 满足下边的条件可以考虑使用静态化&#xff1a; 1、该页面被访问频率高&#xff0c;比如&#xff1a;商品信息展示、专家介绍页面等…...

读懂AUTOSAR:PduR模块--使用FIFO

简介&#xff1a; 现在的汽车越来越智能化和复杂化&#xff0c;这得益于汽车软件和电子控制系统的发展。为了帮助汽车制造商和供应商更好地开发和管理汽车软件&#xff0c;全球性的汽车软件开发标准——AUTOSAR&#xff08;AUTomotive Open System ARchitecture&#xff09;应…...

对象的比较(数据结构系列12)

目录 前言&#xff1a; 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. 题目 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如&#xff0c;arr [1,2,3] &#xff0c;以下这些都可以视作 arr 的排列&#xff1a;[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地&…...

ToBeWritten之理解嵌入式Web HTTP协议

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…...

顶级程序员的成长之路1

本文关注的问题是程序员的水平究竟应该按照什么样的不同层级而逐渐提高&#xff1f;或者说&#xff0c;在学习编程的过程中&#xff0c;每一个阶段究竟应当设定什么样的目标才比较合理&#xff1f;本文的内容主要借鉴了周伟明先生的专栏文章《程序员的十层楼》[86]。注意本文讨…...

第三代api自动化测试框架使用教程(pytest+allure+sql+yaml)

使用教程一、配置1、环境配置2、框架配置3、启动入口二、用例编写1、用例模板2、参数依赖写法2、函数&#xff08;方法插件&#xff09;写法3、接口上传文件和表单参数4、接口上传json参数5、接口无数据填写6、code断言7、body断言7、json断言8、sql断言9、完整断言写法&#x…...

Qt——实现一个获取本机网络信息的界面

效果展现 代码实现 networkinformation.h&#xff1a; #ifndef NETWORKINFORMATION_H #define NETWORKINFORMATION_H#include <QMainWindow> #include <QLabel> #include <QLineEdit> #include <QPushButton>class NetworkInformation : public QMai…...

全面深入了解接口自动化,看完还不会我报地址

一、自动化分类 &#xff08;1&#xff09;接口自动化 python/javarequestsunittest框架来实现 python/javaRF&#xff08;RobotFramework&#xff09;框架来实现——对于编程要求不高 &#xff08;2&#xff09;Web UI功能自动化 python/javaseleniumunittestddtPO框架来实…...

Python 小型项目大全 61~65

六十一、ROT13 密码 原文&#xff1a;http://inventwithpython.com/bigbookpython/project61.html ROT13 密码是最简单的加密算法之一&#xff0c;代表“旋转 13 个空格”密码将字母A到Z表示为数字 0 到 25&#xff0c;加密后的字母距离明文字母 13 个空格&#xff1a; A变成N&…...

Hlog

Hlog 简介 Hlog是Hbase实现WAL(Write ahead log )方式产生的日志信息 &#xff0c; 内部是一个简单的顺序日志。每个RegionServer对应1个Hlog(备注&#xff1a;1.X版本的可以开启MultiWAL功能&#xff0c;允许对应多个Hlog),所有对于该RegionServer的写入都会被记录到Hlog中。H…...

学编程应该选择什么操作系统?

今天来聊一个老生常谈的问题&#xff0c;学编程时到底选择什么操作系统&#xff1f;Mac、Windows&#xff0c;还是别的什么。。 作为一个每种操作系统都用过很多年的程序员&#xff0c;我会结合我自己的经历来给大家一些参考和建议。 接下来先分别聊聊每种操作系统的优点和不…...

Oracle基础部分二(伪列/表、单个函数、空值处理、行列转换、分析函数、集合运算)

Oracle基础部分二&#xff08;伪列/表、单个函数、空值处理、行列转换、分析函数、集合运算&#xff09;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&#xff1a;原码&#xff0c;反码&#xff0c;补码和常见的数据类型取值范围&#xff0c;溢出 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;此时学会c的话&#xff0c; 我所知道的周边的会c的同学&#xff0c;可手握…...

Java题目训练——年终奖和迷宫问题

目录 一、年终奖 二、迷宫问题 一、年终奖 题目描述&#xff1a; 小东所在公司要发年终奖&#xff0c;而小东恰好获得了最高福利&#xff0c;他要在公司年会上参与一个抽奖游戏&#xff0c;游戏在一个6*6的棋盘上进行&#xff0c;上面放着36个价值不等的礼物&#xff0c; 每…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...