three.js 鼠标左右拖动改变玩家视角

news2025/1/16 1:42:21

这里主要用到了 一个方法   obj.getWorldDirection();  

obj.getWorldDirection()表示的获取obj对象自身z轴正方向在世界坐标空间中的方向。

按下 W键前进运动;

 

<template>
  <div>
    <el-container>
      <el-main>
        <div class="box-card-left">
          <div id="threejs"></div>
          {{ movementX }}
        </div>
      </el-main>
    </el-container>
  </div>
</template>s
<script>
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import TWEEN from '@tweenjs/tween.js';
export default {
  data() {
    return {
      scene: null,
      camera: null,
      renderer: null,
      res1: null,
      res2: null,
      clock: null,
      left_mouse_down: false,
      keyState: {
        W: false,
        S: false,
        A: false,
        D: false,
      },
      left_rotation: true, // 向左旋转的标志
      right_rotation: true, // 向右旋转的标志
      VW: new this.$three.Vector3(0, 0, 0),
      VS: new this.$three.Vector3(0, 0, 0),
      curr_v: new this.$three.Vector3(0, 0, 0),
      person: null,
      movementX: null,
      deltaTime: 0,
      a: 60, // 加速度
      damping: -0.04,
    };
  },
  created() {},
  mounted() {
    this.init();
  },
  methods: {
    goBack() {
      this.$router.go(-1);
    },
    init() {
      // 创建场景对象
      this.scene = new this.$three.Scene();
      // 创建坐标轴辅助对象
      const axesHelper = new this.$three.AxesHelper(100);
      this.scene.add(axesHelper);
      // 创建时钟对象
      this.clock = new this.$three.Clock();
      // 创建环境光对象
      const ambientLight = new this.$three.AmbientLight(0xffffff, 6);
      this.scene.add(ambientLight);
      // this.createMesh();
      // 创建相机对象
      this.camera = new this.$three.PerspectiveCamera(60,1,0.01,2000);
      // this.camera.position.set(0,5,-5);
      // this.camera.lookAt(0,0,0);
      // 创建渲染器对象
      this.renderer = new this.$three.WebGLRenderer();
      this.renderer.setSize(1000,800);
      // 创建gltfLoader加载器对象
      const gltfLoader = new GLTFLoader();
      gltfLoader.load("models/gltf/person2/scene.gltf", gltf => {
        this.person = gltf.scene;
        // 将相机添加到人物模型上
        this.person.add(this.camera);
        // 调整相机位置
        this.camera.position.add(new this.$three.Vector3(0,5,-6));
        this.camera.translateZ(-1);
        let camera_look_position = this.person.position.clone().add(new this.$three.Vector3(0,4,0));
        // 设置相机指向
        this.camera.lookAt(camera_look_position);
        this.scene.add(gltf.scene);
        this.renderer.render(this.scene, this.camera);
        window.document.getElementById("threejs").appendChild(this.renderer.domElement);
      })
      // 监听事件方法
      this.addEventListenerFn();
      this.renderLoop();
    },
    createMesh() {
      const geometry = new this.$three.BoxGeometry(1,1,1);
      const material = new this.$three.MeshBasicMaterial({color: 0xffaadd});
      const mesh = new this.$three.Mesh(geometry, material);
      // mesh.rotateY(Math.PI / 2);
      const dir = new this.$three.Vector3();
      mesh.getWorldDirection(dir);
      this.scene.add(mesh);
      console.log('dir', dir);
    },
    addEventListenerFn() {
      document.addEventListener("mousemove", e => {
        // 鼠标左键按下的情况
        if(this.left_mouse_down) {
          this.movementX = e.movementX;
          this.person.rotation.y -= e.movementX / 100;
          // this.camera.rotateY(e.movementX / 100);
        const dir = new this.$three.Vector3();
        this.person.children[0].getWorldDirection(dir);
          this.renderer.render(this.scene, this.camera);
        }
      })
      document.addEventListener("mousedown", e => {
        // e.button == 0 左键;e.button == 2 右键;
        if(e.button == 0) {
          this.left_mouse_down = true;
        }
      })
      document.addEventListener("mouseup", e => {
        // e.button == 0 左键;e.button == 2 右键;
        if(e.button == 0) {
          this.left_mouse_down = false;
        }
      })
      // 监听键盘按下
      document.addEventListener("keydown", e => {
        // 如果按下的是  w键
        if(e.code == "KeyW") {
          this.keyState.W = true;
        }
        if(e.code == "KeyS") {
          this.keyState.S = true;
        }
      })
      // 监听键盘弹起
      document.addEventListener("keyup", e => {
        // 如果按下的是  w键
        if(e.code == "KeyW") {
          this.keyState.W = false;
        }
        if(e.code == "KeyS") {
          this.keyState.S = false;
        }
      })
    },
    renderLoop() {
      let deltaTime = this.clock.getDelta();

      if(this.keyState.W) {
        const front = new this.$three.Vector3();
        this.person.getWorldDirection(front);
        let person_v = this.curr_v.clone().add(front.multiplyScalar(deltaTime * this.a));
        const pos = person_v.clone().multiplyScalar(deltaTime);
        this.person.position.add(pos);
      }
      if(this.keyState.S) {
        const front = new this.$three.Vector3();
        this.person.getWorldDirection(front);
        let person_v = this.curr_v.clone().add(front.multiplyScalar(deltaTime * (-this.a)));
        const pos = person_v.clone().multiplyScalar(deltaTime);
        this.person.position.add(pos);
      }
      this.renderer.render(this.scene, this.camera);
      window.requestAnimationFrame(this.renderLoop);
    },
  },
};
</script>
<style lang="less" scoped>
.box-card-left {
  display: flex;
  align-items: flex-start;
  flex-direction: row;
  width: 100%;
  .box-right {
    img {
      width: 500px;
      user-select: none;
    }
  }
}
</style>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt(C++) | QPropertyAnimation动画(移动、缩放、透明)篇

动画类继承关系图 # QPropertyAnimation QPropertyAnimation是一个可以在Qt应用程序中使用的动画框架。它可以用于创建各种动画效果,包括但不限于以下几种: 1. 移动动画:可以将一个对象从一个位置平滑地移动到另一个位置。比如,你可以创建一个按钮,当用户点击它时,按钮…

Python语法基础

Python 运行方式 交互解释器&#xff1a;进入交互解释器 Pycharm 里面有个 Terminal 终端&#xff0c;点击即可进入Python的交互环境 语句快缩进 同行多个语句 输出语句:print 输入语句: 变量定义: 变量赋值: 运算符: 基本数字类型: 数字表示方法: 定义字符串: 定义列表:

【Vue3】深入理解Vue3路由器的工作原理to的两种写法

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

整块代码自动生成、智能括号匹配……CodeGeeX编程提效,功能再升级!

CodeGeeX插件功能持续打磨&#xff0c;希望成为开发者更高效的智能编程工具&#xff0c;提高开发速度和代码质量。今天介绍VSCode中最新的v2.4.0版本插件新功能&#xff0c;让你在编写代码时更加得心应手。 一、新增block代码块生成的设置 CodeGeeX插件中&#xff0c;以往针对…

读西游记第一回:西游记世界格局

天地之数&#xff1a; 元&#xff1a;十二万九千六百岁&#xff08;129600年&#xff09; 1元12会&#xff1a;子、丑、寅、卯、巳、午、未、申、酉、戌、亥。每会18000年。与12地支对应。 亥会期&#xff1a;前5400年混沌期&#xff0c;后5400年&#xff0c;盘古开天辟地&am…

【阿里云系列】-ACK的Java应用POD无法访问云数据库Redis

问题介绍 如下图所示&#xff0c;是ACK集群的POD访问阿里云的云数据库Redis&#xff0c;如何实现访问呢 配置步骤 要实现ACK集群内的所有POD都可以访问云数据库Redis&#xff0c;则需要在Redsi的白名单里增加源IP或网段&#xff0c;如下图所示 注意&#xff1a; 以上添加…

小型校园网配置笔记

1&#xff0c;搭建网络拓扑图 LSW1:三层交换机命令&#xff1a; <Huawei>sys [Huawei]undo info-center enable Info: Information center is disabled. [Huawei]vlan batch 10 20 30 40 100 101 [Huawei]int vlan 10 [Huawei-Vlanif10]ip add 192.168.10.254 24 …

PyTorch之完整的神经网络模型训练

简单的示例&#xff1a; 在PyTorch中&#xff0c;可以使用nn.Module类来定义神经网络模型。以下是一个示例的神经网络模型定义的代码&#xff1a; import torch import torch.nn as nnclass MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()# 定义神经…

sqllab第九关通关笔记

知识点&#xff1a; 时间盲注&#xff1a;利用休眠时间进行判断是否注入成功利用bp时注意把timeout时间修改一下 首先判断注入类型 构造id1/0 返回正常信息&#xff0c;应该是字符型注入 构造id1 返回正常信息&#xff0c;欸&#xff0c;这就怪了 构造id1 正常显示内容&am…

Lombok简介、使用、工作原理、优缺点

学习目标&#xff1a; 目标 Lombok简介、使用、工作原理、优缺点 学习内容&#xff1a; 内容 定义 Lombok 是一个 Java 库&#xff0c;它提供了很多有用的注解来简化 Java 代码的编写。 作用&#xff1a; 使用 Lombok 可以用一些简洁的注解来自动生成大量常见的 Java 代码&a…

EI会议----2024年控制技术、自动化与绿色城市规划国际学术会议(TAUGCP 2024)

EI会议----2024年控制技术、自动化与绿色城市规划国际学术会议(TAUGCP 2024) 2024 International Conference on Control Technology, Automation and Green Urban Planning(TAUGCP 2024) 大会主题&#xff1a;&#xff08;主题包括但不限于这些,更多详细主题请咨询苏老师&am…

缓存的使用

文章目录 1.为什么要有缓存&#xff1f;2.缓存使用场景3.缓存分类4.缓存使用模式5.淘汰策略6.缓存的崩溃与修复7.缓存最佳实践参考文献 1.为什么要有缓存&#xff1f; 数据访问具有局部性&#xff0c;符合二八定律&#xff1a;80% 的数据访问集中在 20% 的数据上&#xff0c;这…

Nuxt3: useFetch使用过程常见一种报错

一、问题描述 先看一段代码&#xff1a; <script setup> const fetchData async () > {const { data, error } await useFetch(https://api.publicapis.org/entries);const { data: data2, error: error2 } await useFetch(https://api.publicapis.org/entries);…

展会邀约 | 加速科技将携重磅产品亮相SEMICON China 2024

SEMICON China 2024将于3月20日-3月22日在上海新国际博览中心隆重举行。展会期间&#xff0c;加速科技将携重磅产品高性能数模混合信号测试机ST2500EX、LCD Driver测试机Flex10K-L、高密度数模混合信号测试系统ST2500E、高性能数模混合信号测试系统ST2500A亮相此次行业盛会&…

[Java、Android面试]_02_HashMap的原理

本人今年参加了很多面试&#xff0c;也有幸拿到了一些大厂的offer&#xff0c;整理了众多面试资料&#xff0c;后续还会分享众多面试资料&#xff0c;感兴趣的朋友可收藏关注。由于时间有限&#xff0c;只能每天整理一点&#xff0c;分享一点儿&#xff01; 现分享如下&#xf…

vue3/vue2若依框架对比,点击新增编辑跳转到新页面(新增编辑共用代码)

vue2若依框架&#xff1a; router里面定义好&#xff0c;编辑里面添加一个id {path: /filmManagement,component: Layout,hidden: true,redirect: noredirect,children: [{path: editFilmDetail,component: () > import(/views/filmManagement/editFilmDetail),name: editFi…

【Mac】鼠标控制\移动\调整窗口大小BBT|边缘触发调整音量\切换桌面

一直在 win 习惯了通过鼠标的侧键来控制窗口的位置、大小&#xff0c;现在找到心的解决方案了&#xff0c;通过 BBT 设置侧键按下\抬起几颗。 以下解决方案的截图&#xff0c;其中还包括了其他操作优化方案&#xff1b; 滚轮配合 cmd 键调节页面大小&#xff1b;配合 option 键…

探索C++中的动态数组:实现自己的Vector容器

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f648;个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…

算法思想总结:双指针算法

一、移动零 . - 力扣&#xff08;LeetCode&#xff09; 移动零 该题重要信息&#xff1a;1、保持非0元素的相对位置。2、原地对数组进行操作 思路&#xff1a;双指针算法 class Solution { public:void moveZeroes(vector<int>& nums){int nnums.size();for(int cur…

Elasticsearch:在本地使用 Gemma LLM 对私人数据进行问答

在本笔记本中&#xff0c;我们的目标是利用 Google 的 Gemma 模型开发 RAG 系统。 我们将使用 Elastic 的 ELSER 模型生成向量并将其存储在 Elasticsearch 中。 此外&#xff0c;我们将探索语义检索技术&#xff0c;并将最热门的搜索结果作为 Gemma 模型的上下文窗口呈现。 此外…