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

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...