当前位置: 首页 > 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; 每…...

[Python3高阶编程] - 异步编程深度学习指南二(补充1): 什么是 Barrier 原语 【异步!!!】

asyncio.Barrier 是 Python 3.11&#xff08;2022 年 10 月&#xff09;新增的高级同步原语&#xff0c;用于解决特定并发协作场景。一、Barrier 产生的背景&#xff1a;为什么需要它&#xff1f;核心问题&#xff1a;“多协程阶段对齐”在并发编程中&#xff0c;经常遇到这样的…...

4步轻松搞定Windows系统优化:Win11Debloat让你的电脑重获新生

4步轻松搞定Windows系统优化&#xff1a;Win11Debloat让你的电脑重获新生 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutter…...

Qwerty Learner设计系统构建:组件库与样式指南终极指南

Qwerty Learner设计系统构建&#xff1a;组件库与样式指南终极指南 【免费下载链接】qwerty-learner 为键盘工作者设计的单词记忆与英语肌肉记忆锻炼软件 / Words learning and English muscle memory training software designed for keyboard workers 项目地址: https://gi…...

下篇:那个听声辨位的侦探后来破了大案——AI中隐马尔可夫模型的类型与作用,以及它为什么还在被使用

我们说了隐马尔可夫模型是一个“只能听声、不能见人”的侦探&#xff0c;靠着一串声音推理出隔壁房间在发生什么。现在的问题是&#xff1a;它到底有哪些具体的“形态”&#xff1f;不同类型的隐马尔可夫模型分别擅长什么&#xff1f;这个“老古董”在今天还能干什么&#xff1…...

如何在3天内快速掌握音频驱动面部动画技术?完整实战指南 [特殊字符]

如何在3天内快速掌握音频驱动面部动画技术&#xff1f;完整实战指南 &#x1f680; 【免费下载链接】FACEGOOD-Audio2Face http://www.facegood.cc 项目地址: https://gitcode.com/gh_mirrors/fa/FACEGOOD-Audio2Face 想要让虚拟角色拥有逼真的面部表情吗&#xff1f;FA…...

002:RAG 入门-LangChain 读取文本

正文 异步/等待解决了什么问题&#xff1f; 在传统同步I/O操作中&#xff08;如文件读取或Web API调用&#xff09;&#xff0c;调用线程会被阻塞直到操作完成。这在UI应用中会导致界面冻结&#xff0c;在服务器应用中则造成线程资源的浪费。async/await通过非阻塞的异步操作解…...

ExplorerBlurMica终极指南:让你的Windows文件资源管理器焕然一新

ExplorerBlurMica终极指南&#xff1a;让你的Windows文件资源管理器焕然一新 【免费下载链接】ExplorerBlurMica Add background Blur effect or Acrylic (Mica for win11) effect to explorer for win10 and win11 项目地址: https://gitcode.com/gh_mirrors/ex/ExplorerBlu…...

3大实战场景解析:如何用FakeLocation实现Android应用级GPS伪装

3大实战场景解析&#xff1a;如何用FakeLocation实现Android应用级GPS伪装 【免费下载链接】FakeLocation Xposed module to mock locations per app. 项目地址: https://gitcode.com/gh_mirrors/fak/FakeLocation FakeLocation是一款基于Xposed框架的Android位置模拟工…...

不止是拆网卡:以联想ThinkCentre M7131z为例,聊聊老旧一体机的升级改造可能性

联想ThinkCentre M7131z改造指南&#xff1a;从拆网卡到全面性能升级 老旧商用一体机往往被贴上"性能瓶颈"的标签&#xff0c;但联想ThinkCentre M7131z系列却隐藏着令人惊喜的改造潜力。这台发布于2015年前后的商用一体机&#xff0c;凭借其模块化设计和充足的内部空…...

MediaPipe农业智能化:10个精准农业与作物监测的创新应用

MediaPipe农业智能化&#xff1a;10个精准农业与作物监测的创新应用 【免费下载链接】mediapipe Cross-platform, customizable ML solutions for live and streaming media. 项目地址: https://gitcode.com/GitHub_Trending/med/mediapipe MediaPipe作为谷歌开源的跨平…...