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

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

SQL Server 触发器调用存储过程实现发送 HTTP 请求

文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...