threejs (二) 相机

正交相机

在这里插入图片描述

const camera = new THREE.OrthographicCamera(
          -aspect,
          aspect,
          aspect,
          -aspect,
          0.1, //进平面
          1000 //远平面
        ); // 透视相机

创建相机辅助线

const cameraHelper = new THREE.CameraHelper(this.camera);

在这里插入图片描述
创建一个透视相机观察正交相机

 // 创建透视相机
        const watchCamera = new THREE.PerspectiveCamera(
          75,
          this.width / this.height
        );
        // 在正交投影后,距离人眼更近
        watchCamera.position.set(2, 2, 6);
        watchCamera.lookAt(this.scene.position);
        this.scene.add(watchCamera);
        this.camera = watchCamera;
        this.watchCamera = watchCamera;

上面的
在这里插入图片描述

GUI调试相机参数:dat.gui
可以配置设置对象的属性:可以是numberboolean类型和方法类型,点击gui插件方法名称时,会执行改方法,可以通过addColor调整颜色。
npm install --save dat.gui

import * as dat from 'dat.gui';
...,
const gui = new dat.GUI();
        let params = {
          wireframe: false,
          switchCamera: () => {
            if (this.camera.type === 'OrthographicCamera') {
              this.camera = this.watchCamera;
              // 鼠标控制拖动开启
              this.orbitControls.enabled = true;
            } else {
              this.camera = this.otherCamera;
              this.orbitControls.enabled = false;
            }
          },
        };
        gui.add(this.camera.position, 'x', 0.1, 10, 0.1);
        gui.add(this.camera, 'near', 0.01, 10, 0.01).onChange((val) => {
          this.camera.near = val;
          // 矩阵更新函数
          this.camera.updateProjectionMatrix();
        });
        gui.add(this.camera, 'far', 1, 100, 1).onChange((val) => {
          this.camera.far = val;
          // 矩阵更新函数
          this.camera.updateProjectionMatrix();
        });
        gui.add(this.camera, 'zoom', 0.1, 10, 0.1).onChange((val) => {
          this.camera.zoom = val;
          // 矩阵更新函数
          this.camera.updateProjectionMatrix();
        });
        gui.add(params, 'wireframe').onChange((val) => {
          this.mesh.material.wireframe = val;
        });
        gui.add(params, 'switchCamera');
        gui.addColor(params, 'color').onChange((val) => {
          this.mesh.material.color.set(val);
        });

在这里插入图片描述

透视相机

透视相机的可视角度,使用一个透视相机观察透视相机
在这里插入图片描述
在这里插入图片描述

包围盒

threejs默认没有对物体进行包围盒计算,mesh.geometry.boundingBox默认为null,通过调用mesh.geometry.computeBoundingBox()方法生成物体包围盒。
检测包围盒是否在视锥体以内

// 视锥体:用于确定相机视野内的东西
        const frustum = new THREE.Frustum();
        this.camera.updateProjectionMatrix(); //保证拿到最新正确的结果
        // 根据投影矩阵 matrix 来设置当前视椎体的六个面 参数为投影矩阵
        frustum.setFromProjectionMatrix(
          new THREE.Matrix4().multiplyMatrices(
            this.camera.projectionMatrix, //投影变化矩阵
            this.camera.matrixWorldInverse //相机的世界变换矩阵的逆矩阵
          )
        );
        const result = frustum.intersectsBox(this.mesh.geometry.boundingBox);
        console.log(result);

在这里插入图片描述

相机漫游(模拟飞行器)

本质是让相机沿着曲线移动
curver

创建曲线

import { HeartCurve } from 'three/examples/jsm/curves/CurveExtras';

		curveGenerator() {
        const curve = new HeartCurve(1);
        // 管道缓冲几何体
        const tubeGeometry = new THREE.TubeGeometry(curve, 200, 0.01, 8, true);
        const material = new THREE.MeshBasicMaterial({
          color: 0x00ff00,
        });
        const tubeMesh = new THREE.Mesh(tubeGeometry, material);
        // 把曲线分割为1000段
        this.points = curve.getPoints(1500);
        // 心旋转90度
        tubeMesh.rotation.x = -Math.PI / 2;
        this.scene.add(tubeMesh);
        this.curve = curve;
		// 设置一个虚拟相机的小球 方便看效果
        const sphereGeometry = new THREE.SphereGeometry(0.5, 32, 64);
        const sphereMaterial = new THREE.MeshBasicMaterial({
          color: 0xffff00,
        });
        const sphereMesh = new THREE.Mesh(sphereGeometry, sphereMaterial);
        sphereMesh.position.copy(this.pCamera.position);
        this.scene.add(sphereMesh);
        this.sphereMesh = sphereMesh;
      },

移动相机

将路径分为多个点,让相机沿着每个点运动

moveCamera() {
        const index = this.count % this.points.length;
        const point = this.points[index];
        const nextPoint =
          this.points[index + 1 >= this.points.length ? 0 : index + 1];
        //  this.pCamera.position.set(point.x, point.y, point.z);
        this.pCamera.position.set(point.x, 0, -point.y);
        // this.pCamera.lookAt(nextPoint.x, 0, -nextPoint.y); //让人眼视角沿着路径移动
        //  this.sphereMesh.position.set(point.x, point.y, point.z);
        this.sphereMesh.position.set(point.x, 0, -point.y);
        this.count++;
      },

在这里插入图片描述
tick方法中调用moveCamera相机移动方法,可以看到不断运动的效果,但是相机目前是在垂直方向运行,如果想修改为水平方向上运行,先将桃心旋转90度tubeMesh.rotation.x = -Math.PI / 2;,以红色为轴旋转桃心。
然后修改相机和小球的移动,可见一直在y轴的平面上运动 y固定为0,z轴原本为0,改为沿着y轴运动
在这里插入图片描述

控制器

轨道控制器

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

const orbitControls = new OrbitControls(camera, canvas);

orbitControls.enableDamping = true; // 启用惯性效果
orbitControls.dampingFactor = 0.1; // 阻尼系数
orbitControls.enablePan = true; // 启用或禁用相机平移(Mac按住cmd生效)
orbitControls.panSpeed = 1; // 位移的速度
orbitControls.autoRotate = true; // 自动围绕目标旋转
orbitControls.autoRotateSpeed = 2; // 控制旋转速度
orbitControls.enabled = true; // 是否启用
orbitControls.enableRotate = true; // 启用相机水平或垂直旋转
orbitControls.enableZoom = true; // 启用相机缩放
orbitControls.minZoom = 0; // 限制缩放
orbitControls.maxZoom = 10; // 限制缩放
orbitControls.zoomSpeed = 2; // 缩放速度
orbitControls.minDistance = 0; // 将相机向内移动多少(仅适用于PerspectiveCamera)
orbitControls.maxDistance = 0; // 将相机向外移动多少(仅适用于PerspectiveCamera)
orbitControls.target.y = 2; // 改变初始视角的位置
// ...

拖拽控制器

import { DragControls } from 'three/examples/jsm/controls/DragControls';

const dragControls = new DragControls([objects], camera, canvas);

拖拽控制器与轨道控制器的放大缩小功能冲突解决

dragControls.addEventListener('dragstart', function(e) {
  orbitControls.enabled = false;
});
dragControls.addEventListener('dragend', e => {
  orbitControls.enabled = true;
});

多相机控制

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/125099.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【算法与数据结构】39、LeetCode组合总和

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析:这道题当中数字可以多次使用,那么我们在递归语句当中不能直接找下一个candidate的元素&…

两台linux虚拟机之间实现免密登录

主要实现两台虚拟机之间的免密登录,总所周知,虚拟机之间登录使用的协议是ssh协议,端口号是 22 主机 创建对应的加密文件 [rootweb-2 ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.s…

docker容器中运行jar 出现invalid or corrupt jarfile

1,背景: 在本地java开发完毕之后,想要打包成docker镜像,方便安装。由于本地没有docker环境,也懒得装了。有一台测试的linux机器可以使用,所以先在本地打包生成xxx.jar,然后拷贝到有docker环境的…

vite + electron引入itk报错

代码 import { readImageArrayBuffer } from itk-wasm console.log(readImageArrayBuffer)通过itk-wasm官网,创建新的项目vitevue(vue2或者vue3),都没问题。加入electeon后包此错。通过排查,意外找到原因,…

抵御数字威胁的铠甲——发现迅软DSE加密软件在企业保护中的关键角色

目前国内有自主知识产权和研发成果的企业,它们的电子文档大都以明文的方式存储在计算机硬盘中,电子格式存储的重要机密信息却由于传播的便利性和快捷性,对分发出去的文档无法控制,大的增加了管理的复杂程度,这部分信息…

Swift--量值与基本数据类型

系列文章目录 第一章: Swift–量值与基本数据类型 文章目录 系列文章目录前言对学习过程做一个记录 变量和常量命名规范注释 元祖类型可选类型拆包 typealias 前言 对学习过程做一个记录 提示:以下是本篇文章正文内容,下面案例可供参考 变量和常量 …

家用工作站方案:ThinkBook 14 2023 版

本篇文章聊聊今年双十一,我新购置的家用工作站设备:ThinkBook 14 2023,一台五千元价位,没有显卡的笔记本。我为什么选择它,它又能做些什么。 写在前面 2021 年年中的时候,我写过一篇《廉价的家用工作站方…

开源知识库软件xwiki在Windows下的安装

文章目录 开源知识库软件-xwiki在windows上的部署0、参考文档1、前置环境准备1.1、Windows版本及系统配置1.2、JDK11安装1.3、Tomcat9安装1.4、MySQL5.7数据库的安装 2、xwiki安装3、配置3.1、修改配置支持对文档内容进行搜索 4、问题解决4.1、附件无法上传问题4.1、附件无法下…

【309. 买卖股票的最佳时机含冷冻期】

目录 一、题目解析 二、算法原理 三、代码实现 class Solution { public:int maxProfit(vector<int>& prices) {int nprices.size();vector<vector<int>> dp(n,vector<int>(3));dp[0][0]-prices[0];dp[0][1]0;dp[0][2]0;for(int i1;i<n;i){dp…

Apipost发起请求,能正确返回,日志却打印java.io.EOFException: null 的原因

http响应头首部Content-Length - 程序员大本营 http响应头首部Content-Length HTTP Content-Length深入实践-CSDN博客 用了这么久HTTP, 你是否了解Content-Length?-CSDN博客 具体分析可看上面参考文章。 解决办法&#xff1a;可在请求头加上Content-Length&#xff0c;准确…

关于卷积神经网络的多通道

多通道输入 当输入的数据包含多个通道时&#xff0c;我们需要构造一个与输入通道数相同通道数的卷积核&#xff0c;从而能够和输入数据做卷积运算。 假设输入的形状为n∗n&#xff0c;通道数为ci​&#xff0c;卷积核的形状为f∗f&#xff0c;此时&#xff0c;每一个输入通道都…

通过一道题目带你深入了解WAF特性、PHP超级打印函数、ASCII码chr()对应表等原理[RoarCTF 2019]Easy Calc 1

题目环境&#xff1a; 依此输入以下内容并查看回显结果 11 1’ index.php ls 到这里没思路了 F12查看源代码 一定要仔细看啊&#xff0c;差点没找到&#xff0c;笑哭 访问calc.php文件 果然有点东西 PHP代码审计 error_reporting(0);关闭错误报告 通过GET方式传参的参数num sho…

ssm+vue的高校学生课堂考勤系统设计与实现(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的高校学生课堂考勤系统设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转…

开发知识点-NodeJs-npm/Pnpm/Vite/Yarn包管理器

包管理器 vue-cli-service 不是内部或外部命令&#xff0c;也不是可运行的程序npm 全局变量pnpmPnpm介绍ViteYarn ‘vue-cli-service’ 不是内部或外部命令&#xff0c;也不是可运行的程序 yarn yarn add vue-amap yarn add vue-amap ant-design-vue npm 全局变量 换主机 新…

AVL树的插入详解

AVL树 为什么有AVL树的出呢&#xff1f;其实我们用的map/multimap/set/multiset的底层都是二叉搜索树&#xff0c;但是二叉搜索树有一个很大的缺陷&#xff0c;就是当往树中插入的元素有序或者接近有序&#xff0c;二叉搜索树就会退化成单支树&#xff0c;时间复杂度会退化成…

计算机服务器中了locked勒索病毒怎么办,勒索病毒解密,数据恢复

随着网络技术的不断成熟&#xff0c;网络中存在的病毒威胁也不断增多&#xff0c;近期&#xff0c;云天数据恢复中心陆续接到很多企业的求助&#xff0c;企业的计算机服务器数据库遭到了勒索病毒攻击&#xff0c;并且勒索病毒的攻击与加密形式也发生了许多变化。其中攻击次数较…

记一次 Android 周期性句柄泄漏的排查

滴滴国际化外卖 Android 商户端正常迭代版本过程中&#xff0c;新版本发布并且线上稳定一段时间后&#xff0c;突然触发线上 Crash 报警。 第一次排查发现是在依赖的底层平台 so 库中崩溃&#xff0c;经过沟通了解到其之前也存在过崩溃问题&#xff0c;所以升级相关底层 so 版本…

Linux mx6ull-驱动(1)hello

编写第一个驱动&#xff0c;hello_drv 一、获取内核、编译内核。 这里为什么要获取内核呢&#xff0c;因为我们写的是驱动程序&#xff0c;而不是裸机程序。也就是我们的板子已经烧入进去了uboot、内核&#xff0c;根文件。然后我们要在这个板子的内核的基础上&#xff0c;来…

【uniapp】签名组件,兼容vue2vue3

网上找了个源码改吧改吧&#xff0c;清除了没用的功能和兼容性&#xff0c;基于uniapp开发的 样子 vue2 使用方法&#xff0c;具体的可以根据业务自行修改 <signature ref"signature" width"100%" height"410rpx"></signature>confi…

[鹏程杯2023]复现

SecretShare X的20个值和R的21个值已经被全部泄露&#xff0c;X和R都是1024bit的值&#xff0c;此时X总共泄露了32*20 640&#xff0c;于是&#xff0c;此时我们可以使用mt19937将其还原&#xff0c;还原之后&#xff0c;我们往前推20个1024bit的值&#xff0c;便可以求得A的…