ThreeJs功能封装——基础场景创建

一、功能介绍

1、模块功能

* 【模块功能】
* ThreeJs的初始化涉及相机、场景、光源、鼠标操控器、Axe辅助器、渲染循环、自适应根据窗口大小调整等一系列常规基础功能实现。
* 基本上每个项目都要做这些初始化
* 为了项目间方便复用,减少冗余代码,现将这些功能统一封装起来方便调用

2、输入输出

* 【输入】
* 1、ThreeJs的画布所放置的html元素<div>
* 【输出】
* 1、Web3DRender对象
* 【可自定义调整内容】
* 1、相机
* 2、光源
* 3、鼠标操控器
* 4、axe辅助器

二、核心逻辑

1、场景

    __create_scene(){const scene = new THREE.Scene();scene.background = new THREE.Color( 0xAAAAAA );return scene}

2、渲染器

    __create_render(){const renderer = new THREE.WebGLRenderer();renderer.setPixelRatio( window.devicePixelRatio );// 我们需要跟随者canvas_element的大小renderer.setSize(this.canvas_element.clientWidth, this.canvas_element.clientHeight);renderer.toneMapping = THREE.ACESFilmicToneMapping;renderer.toneMappingExposure = 1;this.canvas_element.appendChild(renderer.domElement);return renderer}

3、渲染循环

    _animate(){const self = thisrequestAnimationFrame(animateLoop)this._updateCameraInfo()this.renderer.render(this.scene, this.camera);function animateLoop() {self._animate()}}

4、摄像机

    __create_camera() {const camera = new THREE.PerspectiveCamera(75, this.canvas_element.clientWidth / this.canvas_element.clientHeight, 0.1, 1000);camera.position.set(0.5, 0.6, 0.8); // 设置相机位置camera.lookAt(this.scene.position); // 让相机朝向场景中心return camera}

5、鼠标控制器

    __create_controls() {const controls = new OrbitControls( this.camera, this.renderer.domElement );controls.enableDamping = true;controls.target.set( 0, 0.1, 0 );controls.update();controls.minDistance = 0.5;controls.maxDistance = 1000;controls.maxPolarAngle = 0.5 * Math.PI;return controls}

三、封装代码

/*** 【模块功能】* ThreeJs的初始化涉及相机、场景、光源、鼠标操控器、Axe辅助器、渲染循环、自适应根据窗口大小调整等一系列常规基础功能实现。* 基本上每个项目都要做这些初始化* 为了项目间方便复用,减少冗余代码,现将这些功能统一封装起来方便调用** 【输入】* 1、ThreeJs的画布所放置的html元素<div>* 【输出】* 1、Web3DRender对象* 【可自定义调整内容】* 1、相机* 2、光源* 3、鼠标操控器* 4、axe辅助器* **/import * as THREE from "three"
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';class Web3DRenderer {constructor(canvas_element) {this.canvas_element = canvas_element;this.scene = this.__create_scene()this.renderer = this.__create_render()this.__add_light()this.camera = this.__create_camera()this.controls = this.__create_controls()this.cameraInfo = this.__create_camera_info()this.axesHelper = this.__add_axes_helper()this._animate()// 处理大小调整事件,自适应跟随窗口大小调整window.addEventListener('resize', () => {this.renderer.setSize(this.canvas_element.clientWidth, this.canvas_element.clientHeight);this.camera.aspect = this.canvas_element.clientWidth / this.canvas_element.clientHeight;this.camera.updateProjectionMatrix();this._animate();});}_animate(){const self = thisrequestAnimationFrame(animateLoop)this._updateCameraInfo()this.renderer.render(this.scene, this.camera);function animateLoop() {self._animate()}}__create_camera_info() {const cameraInfoElement = document.createElement("div")this.canvas_element.appendChild(cameraInfoElement)cameraInfoElement.style.position = "absolute"cameraInfoElement.style.top = "1%"cameraInfoElement.style.left = "1%"cameraInfoElement.style.backgroundColor = "black";cameraInfoElement.style.color = "white"cameraInfoElement.style.padding = "10px"cameraInfoElement.style.fontFamily = "Arial, sans-serif"/*         #camera-info {position: absolute;top: 10px;left: 10px;background-color: rgba(0, 0, 0, 0.5);color: white;padding: 10px;font-family: Arial, sans-serif;}*/return cameraInfoElement}_updateCameraInfo() {const camera = this.camerathis.cameraInfo.innerHTML = `摄像头信息:<br>位置: (${camera.position.x.toFixed(2)}, ${camera.position.y.toFixed(2)}, ${camera.position.z.toFixed(2)})<br>角度: (${camera.rotation.x.toFixed(2)}, ${camera.rotation.y.toFixed(2)}, ${camera.rotation.z.toFixed(2)})<br>缩放: ${camera.zoom.toFixed(2)}`;}__create_scene(){const scene = new THREE.Scene();scene.background = new THREE.Color( 0xAAAAAA );return scene}__create_render(){const renderer = new THREE.WebGLRenderer();renderer.setPixelRatio( window.devicePixelRatio );// 我们需要跟随者canvas_element的大小renderer.setSize(this.canvas_element.clientWidth, this.canvas_element.clientHeight);renderer.toneMapping = THREE.ACESFilmicToneMapping;renderer.toneMappingExposure = 1;this.canvas_element.appendChild(renderer.domElement);return renderer}__add_light() {this.scene.add( new THREE.DirectionalLight( 0xffffff, 2 ) );this.scene.add(new THREE.AmbientLight(0xffffff, 2))}__create_camera() {const camera = new THREE.PerspectiveCamera(75, this.canvas_element.clientWidth / this.canvas_element.clientHeight, 0.1, 1000);camera.position.set(0.5, 0.6, 0.8); // 设置相机位置camera.lookAt(this.scene.position); // 让相机朝向场景中心return camera}__create_controls() {const controls = new OrbitControls( this.camera, this.renderer.domElement );controls.enableDamping = true;controls.target.set( 0, 0.1, 0 );controls.update();controls.minDistance = 0.5;controls.maxDistance = 1000;controls.maxPolarAngle = 0.5 * Math.PI;return controls}__add_axes_helper() {//辅助观察的坐标系const axesHelper = new THREE.AxesHelper(100);this.scene.add(axesHelper);return axesHelper}}export {Web3DRenderer
};

四、演示使用代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Three.js GUI复杂案例</title><style>body { margin: 0; overflow: hidden; }#three-3d {width: 100vw;height: 100vh;}</style>
</head>
<body>
<div id="three-3d"></div>
<div id="processBar"></div>
<script type="importmap">{"imports": {"three": "../../three.js-master/build/three.module.js","three/addons/": "../../three.js-master/examples/jsm/","threeBase/": "../"}}
</script>
<script type="module">import * as THREE from "three"import { Web3DRenderer } from 'threeBase/Scene/Web3DRender.js';import {ResourceType, ToLoadResource, ResourceLoader, ResourceLoadState}  from "threeBase/Model/ResourceLoader.js"const threeElement = document.getElementById("three-3d")const web3dRender = new Web3DRenderer(threeElement)const scene = web3dRender.sceneconst glb_resourceInfo = new ToLoadResource("../../three.js-master/examples/models/gltf/SheenChair.glb", ResourceType.GLB_TYPE)const back_textureInfo = new ToLoadResource("../../three.js-master/examples/textures/equirectangular/royal_esplanade_1k.hdr", ResourceType.RGBE_TYPE)const processBarElement = document.getElementById("processBar")const resLoader = new ResourceLoader()resLoader.loadResource([glb_resourceInfo, back_textureInfo], processBarElement, succFunc, processFunc, failFunc)function succFunc(resourceStateInfoList) {const [modelInfo, textureInfo] = resourceStateInfoListscene.add(modelInfo.resouceObj)scene.background = textureInfo.resouceObj;scene.environment = textureInfo.resouceObj;console.log("succ!")}function processFunc(resourceStateInfoList) {console.log("process!")}function failFunc(resourceStateInfoList) {console.log("fail!")}
</script>
</body>
</html>

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows cmd常用命令

文章目录 Windows cmd常用命令一、引言二、文件和目录操作1、查看和切换目录2、文件和目录的创建与删除 三、系统信息与网络配置1、系统信息2、网络配置 四、使用示例五、总结 Windows cmd常用命令 一、引言 Windows 命令提示符&#xff08;cmd&#xff09;是一个强大的工具&a…

保健食品注册数据库<一键查询保健食品信息>

在保健品市场竞争激烈的情况下&#xff0c;企业要如何保障产品合规、信息公开&#xff0c;并且能够迅速应对市场变化呢&#xff1f;查询保健食品注册信息是关键环节。 当下&#xff0c;查询保健食品注册信息主要有两种途径&#xff1a;一是利用国家保健食品注册数据库进行查询…

无所不搜,吾爱制造

吾爱论坛作为众多软件资源爱好者的宝藏之地&#xff0c;汇聚了许多优秀的软件作品&#xff0c;堪称软件界的“福地”。许多技术大佬在这里分享自己的创作。 而今天要介绍的&#xff0c;正是吾爱作者“buyaobushuo”自制的多功能娱乐软件——太极。这款软件基于flet开发&#x…

【C++】详细讲解继承(下)

本篇来继续说说继承。上篇可移步至【C】详细讲解继承&#xff08;上&#xff09; 1.继承与友元 友元关系不能继承 &#xff0c;也就是说基类友元不能访问派⽣类私有和保护成员。 class Student;//前置声明class Same //基类 { public:friend void Fun(const Same& p, con…

【二叉树】4. 判断一颗二叉树是否是平衡二叉树。5. 对称二叉树。6. 二叉树的构建及遍历 7. 二叉树的分层遍历 。

判断一颗二叉树是否是平衡二叉树。OJ链接 可以在求树高度的过程中判断树是否平衡 对称二叉树。OJ链接 二叉树的构建及遍历。OJ链接 注意&#xff1a;public static int i最好把static去掉 否则当有多个测试用例时 i无法重新为0二叉树的分层遍历 。OJ链接 但此题要求返回List…

代码随想录刷题day14(2)|(链表篇)02.07. 链表相交(疑点)

目录 一、链表理论基础 二、链表相交求解思路 三、相关算法题目 四、疑点 一、链表理论基础 代码随想录 二、链表相交求解思路 链表相交时&#xff0c;是结点的位置&#xff0c;也就是指针相同&#xff0c;不是结点的数值相同&#xff1b; 思路&#xff1a;定义两个指针…

IDE提示:因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170

问题情况 不知道为什么我的IDE终端运行命令的时候总提示以下内容&#xff1a; Import-Module : 无法加载文件 D:\Anaconda3\shell\condabin\Conda.psm1&#xff0c;因为在此系统上禁止运行脚本。有关详细信息&#xff0c;请参阅 https:/go.microsoft.com/fwlink/?LinkID1351…

Android中Service在新进程中的启动流程3

目录 1、AMS调用客户端onCreate前的准备工作 2、AMS调用客户端onCreate方法 3、AMS调用客户端的onBind方法 4、AMS调用客户端onStart前的准备 5、AMS调用客户端onStart方法 还是先放上Service启动流程概览图&#xff0c;如下&#xff1a; 上一篇文章&#xff0c; 我们分析…

MVCC底层原理实现

MVCC的实现原理 了解实现原理之前&#xff0c;先理解下面几个组件的内容 1、 当前读和快照读 先普及一下什么是当前读和快照读。 当前读&#xff1a;读取数据的最新版本&#xff0c;并对数据进行加锁。 例如&#xff1a;insert、update、delete、select for update、 sele…

基于Springboot + vue实现的在线装修管理系统

“前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff1a;人工智能学习网站” &#x1f496;学习知识需费心&#xff0c; &#x1f4d5;整理归纳更费神。 &#x1f389;源码免费人人喜…

【多视图学习】显式视图-标签问题:多视图聚类的多方面互补性研究

Explicit View-labels Matter:A Multifacet Complementarity Study of Multi-view Clustering TPAMI 2024 论文链接 代码链接 0.论文摘要 摘要-一致性和互补性是促进多视图聚类&#xff08;MVC&#xff09;的两个关键因素。最近&#xff0c;随着流行的对比学习的引入&#…

Docker Hub 全面解析及应对策略

在现代 DevOps 和容器化应用开发中&#xff0c;Docker Hub 是一个不可或缺的工具。然而&#xff0c;一些地区或企业对 Docker Hub 的访问受到限制&#xff0c;甚至全面禁止。这种现象引发了开发者和运维人员的广泛关注。那么&#xff0c;为什么 Docker Hub 会被禁用&#xff1f…

掌握Spring事务隔离级别,提升并发处理能力

Spring框架支持的事务隔离级别与标准的JDBC隔离级别保持一致&#xff0c;共包括五大隔离级别&#xff0c;它们分别是&#xff1a;DEFAULT&#xff08;默认隔离级别&#xff09;、READ_UNCOMMITTED&#xff08;读未提交&#xff09;、READ_COMMITTED&#xff08;读已提交&#x…

Rabbitmq高级特性之消费方确认

背景&#xff1a; 发送方发送消息之后&#xff0c;到达消费端之后&#xff0c;可能会有以下情况&#xff1a;消息处理成功&#xff0c;消息处理异常。RabbitMQ在向消费者发送消息之后&#xff0c;就会把这条消息给删除掉&#xff0c;那么第二种情况&#xff0c;就会造成消息丢…

[C]基础8.详解操作符

博客主页&#xff1a;算法歌者本篇专栏&#xff1a;[C]您的支持&#xff0c;是我的创作动力。 文章目录 0、总结1、操作符的分类2、二进制和进制转换2.1、2进制转10进制2.2、10进制转2进制2.3、2进制转8进制和16进制 3、原码、反码、补码4、移位操作符4.1 左移操作符4.2 右移操…

【豆包MarsCode蛇年编程大作战】花样贪吃蛇

目录 引言 展示效果 prompt提示信息 第一次提示&#xff08;实现基本功能&#xff09; 初次实现效果 第二次提示&#xff08;美化UI&#xff09; 第一次美化后的效果 第二次美化后的效果 代码展示 实现在线体验链接 码上掘金使用教程 体验地址&#xff1a; 花样贪吃蛇…

【Maui】注销用户,采用“手势”点击label弹窗选择

文章目录 前言一、问题描述二、解决方案三、软件开发&#xff08;源码&#xff09;3.1 方法一&#xff1a;前端绑定3.2 方法二&#xff1a;后端绑定3.3 注销用户的方法 四、项目展示 前言 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架&#xff0c;用于使用 C# 和 XAML 创…

RoCE网络及其协议栈详解(没有中间商赚差价的网络)

引言 随着数据中心对高性能、低延迟通信需求的不断增长&#xff0c;传统的TCP/IP以太网连接已经难以满足现代应用的要求。为了解决这些问题&#xff0c;RDMA&#xff08;Remote Direct Memory Access&#xff09;技术应运而生。RDMA是一种允许网络中的不同计算机直接访问对方内…

数据结构:二叉树—面试题(一)

目录 1、相同的树 2、另一棵树的子树 3、翻转二叉树 4、平衡二叉树 5、对称二叉树 6、二叉树遍历 7、二叉树的分层遍历 1、相同的树 习题链接https://leetcode.cn/problems/same-tree/description/https://leetcode.cn/problems/same-tree/description/ 描述&#xff1a…

2025年新开局!谁在引领汽车AI风潮?

汽车AI革命已来。 在2025年伊始开幕的CES展上&#xff0c;AI汽车、AI座舱无疑成为了今年汽车行业的最大热点。其中不少车企在2025年CES上展示了其新一代AI座舱&#xff0c;为下一代智能汽车的人机交互、场景创新率先打样。 其中&#xff0c;东软集团也携带AI驱动、大数据支撑…