当前位置: 首页 > news >正文

Three的lod技术

 1、资源:https://sbcode.net/threejs/lod/

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import Stats from 'three/examples/jsm/libs/stats.module'
import { GUI } from 'dat.gui'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import TWEEN from '@tweenjs/tween.js'const scene = new THREE.Scene()
scene.background = new THREE.Color(0x87ceeb)const light = new THREE.DirectionalLight(0xffffff, 10)
light.position.set(100, 100, 100)
light.castShadow = true
light.shadow.mapSize.width = 4096
light.shadow.mapSize.height = 4096
light.shadow.camera.near = 0.5
light.shadow.camera.far = 500
light.shadow.camera.left = -500
light.shadow.camera.right = 500
light.shadow.camera.top = 500
light.shadow.camera.bottom = -500
scene.add(light)// const helper = new THREE.CameraHelper(light.shadow.camera);
// scene.add(helper);const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000
)
camera.position.set(4, 5, 7)const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.shadowMap.enabled = true
document.body.appendChild(renderer.domElement)const controls = new OrbitControls(camera, renderer.domElement)
controls.dampingFactor = 0.05
controls.enableDamping = true
controls.screenSpacePanning = falseconst raycaster = new THREE.Raycaster()
const sceneMeshes = new Array()const material = new THREE.MeshPhongMaterial({ color: 0x567d46 })
const planeGeometry = new THREE.PlaneGeometry(1, 1)
planeGeometry.scale(500, 500, 1)
const planeMesh = new THREE.Mesh(planeGeometry, material)
planeMesh.rotateX(-Math.PI / 2)
planeMesh.receiveShadow = true
scene.add(planeMesh)
sceneMeshes.push(planeMesh)let childObjectCount = 2 //how many child meshes are in the tree model. The trunk and leaves are different meshes
const treeCount = 1200 //this many trees are drawn
let treeCounter = 0const positions = new Array()
for (let i = 0; i < treeCount; i++) {positions.push({x: Math.random() * 400 - 200,y: 0,z: Math.random() * 400 - 200,})
}
const scales = new Array()
for (let i = 0; i < treeCount; i++) {scales.push({x: Math.random() * 2 + 1,y: Math.random() * 5 + 1,z: Math.random() * 2 + 1,})
}const treesTypes = ['saplingTree', 'birchTreeWithLeaves', 'tree1WithLeaves']
treesTypes.forEach((treeType) => {let treeHighDetail = new THREE.Object3D()let treeMediumDetail = new THREE.Object3D()let treeLowDetail = new THREE.Object3D()const glTFLoader = new GLTFLoader()glTFLoader.load('models/' + treeType + '_high.glb', (gltf) => {for (let j = 0; j < childObjectCount; j++) {const geometry = (gltf.scene.children[0].children[j] as THREE.Mesh).geometrytreeHighDetail.add(new THREE.Mesh(geometry,(gltf.scene.children[0].children[j] as THREE.Mesh).material))}treeHighDetail.traverse(function (child) {if ((<THREE.Mesh>child).isMesh) {child.castShadow = true}})glTFLoader.load('models/' + treeType + '_medium.glb', (gltf) => {for (let j = 0; j < childObjectCount; j++) {const geometry = (gltf.scene.children[0].children[j] as THREE.Mesh).geometrytreeMediumDetail.add(new THREE.Mesh(geometry,(gltf.scene.children[0].children[j] as THREE.Mesh).material))}treeMediumDetail.traverse(function (child) {if ((<THREE.Mesh>child).isMesh) {child.castShadow = true}})glTFLoader.load('models/' + treeType + '_low.glb', (gltf) => {for (let j = 0; j < childObjectCount; j++) {const geometry = (gltf.scene.children[0].children[j] as THREE.Mesh).geometrytreeLowDetail.add(new THREE.Mesh(geometry,(gltf.scene.children[0].children[j] as THREE.Mesh).material))}treeLowDetail.traverse(function (child) {if ((<THREE.Mesh>child).isMesh) {child.castShadow = true}})for (let i = 0; i < treeCount / treesTypes.length; i++) {const lod = new THREE.LOD()let mesh = treeHighDetail.clone()mesh.scale.copy(scales[treeCounter])lod.addLevel(mesh, 5)mesh = treeMediumDetail.clone()mesh.scale.copy(scales[treeCounter])lod.addLevel(mesh, 10)mesh = treeLowDetail.clone()mesh.scale.copy(scales[treeCounter])lod.addLevel(mesh, 30)lod.position.copy(positions[treeCounter])scene.add(lod)treeCounter++}})})})
})window.addEventListener('resize', onWindowResize, false)
function onWindowResize() {camera.aspect = window.innerWidth / window.innerHeightcamera.updateProjectionMatrix()renderer.setSize(window.innerWidth, window.innerHeight)render()
}renderer.domElement.addEventListener('dblclick', onDoubleClick, false)
function onDoubleClick(event: MouseEvent) {const mouse = {x: (event.clientX / renderer.domElement.clientWidth) * 2 - 1,y: -(event.clientY / renderer.domElement.clientHeight) * 2 + 1,}raycaster.setFromCamera(mouse, camera)const intersects = raycaster.intersectObjects(sceneMeshes, false)if (intersects.length > 0) {const p = intersects[0].pointnew TWEEN.Tween(controls.target).to({x: p.x,y: p.y,z: p.z,},500).easing(TWEEN.Easing.Cubic.Out).start()}
}const stats = new Stats()
document.body.appendChild(stats.dom)var data = {color: light.color.getHex(),shadowMapSizeWidth: 4096,shadowMapSizeHeight: 4096,mapsEnabled: true,
}
const gui = new GUI()
const lightFolder = gui.addFolder('THREE.Light')
lightFolder.addColor(data, 'color').onChange(() => {light.color.setHex(Number(data.color.toString().replace('#', '0x')))
})
lightFolder.add(light, 'intensity', 0, 20, 0.01)
lightFolder.open()const directionalLightFolder = gui.addFolder('THREE.DirectionalLight')
directionalLightFolder.add(light.shadow.camera, 'left', -500, 1, 1).onChange(() => light.shadow.camera.updateProjectionMatrix())
directionalLightFolder.add(light.shadow.camera, 'right', 1, 500, 1).onChange(() => light.shadow.camera.updateProjectionMatrix())
directionalLightFolder.add(light.shadow.camera, 'top', 1, 500, 1).onChange(() => light.shadow.camera.updateProjectionMatrix())
directionalLightFolder.add(light.shadow.camera, 'bottom', -500, -1, 1).onChange(() => light.shadow.camera.updateProjectionMatrix())
directionalLightFolder.add(light.shadow.camera, 'near', 0.1, 500).onChange(() => light.shadow.camera.updateProjectionMatrix())
directionalLightFolder.add(light.shadow.camera, 'far', 0.1, 500).onChange(() => light.shadow.camera.updateProjectionMatrix())
directionalLightFolder.add(data, 'shadowMapSizeWidth', [256, 512, 1024, 2048, 4096]).onChange(() => updateShadowMapSize())
directionalLightFolder.add(data, 'shadowMapSizeHeight', [256, 512, 1024, 2048, 4096]).onChange(() => updateShadowMapSize())
directionalLightFolder.add(light.position, 'x', -50, 50, 0.01)
directionalLightFolder.add(light.position, 'y', -50, 50, 0.01)
directionalLightFolder.add(light.position, 'z', -50, 50, 0.01)
directionalLightFolder.open()function updateShadowMapSize() {light.shadow.mapSize.width = data.shadowMapSizeWidthlight.shadow.mapSize.height = data.shadowMapSizeHeight;(light.shadow.map as any) = null
}function animate() {requestAnimationFrame(animate)controls.update()TWEEN.update()//helper.update()render()stats.update()
}function render() {renderer.render(scene, camera)
}animate()

2、效果

 

相关文章:

Three的lod技术

1、资源&#xff1a;https://sbcode.net/threejs/lod/ import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls import Stats from three/examples/jsm/libs/stats.module import { GUI } from dat.gui import { GLTFLoader }…...

Git配置

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言 前面我们新建了远程仓库并且在Linux上克隆了远程仓库&#xff0c;但是在新建仓库时我们提到会配置gitignore文件&#xff0c;这次我们将会配置他&#xff0c;并给命令起别名。 目录 前言 忽略特殊文件 给命令起别名…...

阻抗控制下机器人接触刚性环境振荡不稳定进行阻抗调节

阻抗接触 刚性环境为ke10000 虚拟阻抗为&#xff1a;kd100&#xff0c;bd10&#xff0c;md1 虚拟阻抗为&#xff1a;kd100&#xff0c;bd10&#xff0c;md5 虚拟阻抗为&#xff1a;kd100&#xff0c;bd10&#xff0c;md10 性能滤波函数的Bode图&#xff1a; bode(1e5/(0.000…...

【鸿蒙应用ArkTS开发系列】-自定义底部菜单列表弹窗

文章目录 前言创建Demo工程创建dialog 文件夹创建ListMenu 接口创建自定义弹窗 ListMenuDialog使用自定义弹窗 打包测试效果演示默认效果菜单带图标效果设置文本颜色效果不同文本颜色效果无标题效果 前言 上一篇文章中我们实现了选择图片、选择文件、拍照的功能 。 链接在这里…...

yolov8添加ca注意力机制

创建文件 coordAtt.py 位置&#xff1a;ultralytics/nn/modules/coordAtt.py ###################### CoordAtt #### start by AI&CV ############################### # https://zhuanlan.zhihu.com/p/655475515 import torch import torch.nn as nn import t…...

linux java后台启动的几种方式

1.使用 nohup 命令 可以使用 nohup 命令启动 Java 应用程序&#xff0c;使其在后台运行&#xff0c;这样即使退出终端或关闭 SSH 连接&#xff0c;Java 应用程序也能继续运行。nohup java -jar myapp.jar &2.使用 & 符号 使用 & 符号可以将 Java 应用程序放到后台…...

selinux-policy-default(2:2.20231119-2)软件包内容详细介绍(5)

接前一篇文章:selinux-policy-default(2:2.20231119-2)软件包内容详细介绍(4) 4. 重点文件内容解析 (1)control/postist文件 上一回解析了control/postinst文件的部分内容,本回继续往下解析。为了便于理解,再次贴出postinst完整代码: #!/bin/sh set -e# summary o…...

代码随想录二刷 |栈与队列 |理论基础

代码随想录二刷 &#xff5c;栈与队列 &#xff5c;理论基础 栈常用操作 队列常用操作 栈与队列是C标准库中的两个数据结构。 栈 栈先进后出&#xff0c;提供 push 和 pop 等接口&#xff0c;所有元素必须符合先进后出的原则&#xff0c;所以栈不提供走访功能&#xff0c;也不…...

java--接口概述

1.认识接口 ①java提供了一个关键字interface&#xff0c;用这个关键字我们可以定义出一个特殊的结构&#xff1a;接口。 ②注意&#xff1a;接口不能创建对象&#xff1b;接口是用来被类实现(implements)的&#xff0c;实现接口的类称为实现类。 ③一个类可以实现多个接口(接…...

出海风潮:中国母婴品牌征服国际市场的机遇与挑战!

近年来&#xff0c;中国母婴品牌在国内市场蓬勃发展的同时&#xff0c;也逐渐将目光投向国际市场。这一趋势不仅受益于中国经济的崛起&#xff0c;还得益于全球市场对高质量母婴产品的不断需求。然而&#xff0c;面对国际市场的机遇&#xff0c;中国母婴品牌同样面临着一系列挑…...

一文读懂MongoDB的知识点(3),惊呆面试官。

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…...

ssm的“魅力”西安宣传网站(有报告)。Javaee项目。

演示视频&#xff1a; ssm的“魅力”西安宣传网站(有报告)。Javaee项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringMvc MybatisVueLayuiElemen…...

怎么让SecureCRT不自动断开连接

SecureCRT 是一个常用的远程连接工具&#xff0c;它可能会因为会话超时或者其他设置而自动断开连接。要防止 SecureCRT 自动断开连接&#xff0c;你可以尝试以下方法&#xff1a; 1. 更改会话选项&#xff1a; 打开 SecureCRT 并连接到你的远程主机后&#xff0c;依次执行以下…...

介绍几种Go语言开发的IDE

文章目录 1.前言2.几种ide2.1 Goland2.2 VsCode示例 2.3 LiteIDE2.4 Eclipse插件GoClipse2.5 Atom2.6 Vim2.7 Sublime Text 3.总结写在最后 1.前言 Go语言作为一种新兴的编程语言&#xff0c;近年来受到了越来越多的关注。 它以其简洁、高效和并发性能而闻名&#xff0c;被广…...

1、设计模式简介(7大原则,3大类)

设计模式有7个原则&#xff1a;单一职责原则、开闭原则、里氏代换原则、依赖倒转原则、接口隔离原则、合成/聚合复用原则、迪米特法则 1&#xff0e;单一职责原则 单一职责原则又称单一功能原则&#xff0c;它规定一个类只有一个职责。如果有多个职责&#xff08;功能&#x…...

华为鲲鹏+银河麒麟V10编译FreeSWITCH1.10.9

# uname -r 4.19.90-17.5.ky10.aarch64 本想编译FreeSWITCH1.10.7&#xff0c;但碰到点问题&#xff0c;后来改1.10.9&#xff0c;相对比较顺利&#xff0c;记录如下&#xff1a; 先安装工具/开发库等&#xff1a; yum install -y git yum install -y wget yum install -y au…...

CFS三层靶机内网渗透

CFS三层靶机内网渗透 一、靶场搭建1.基础参数信息2.靶场搭建2.1网卡配置2.2Target1配置2.2.1 网卡配置2.2.2 Target1 BT配置 2.3Target2配置2.3.1 网卡配置2.3.2 Target2 BT配置 2.4Target3配置 二、内网渗透Target11.1信息收集1.1.1IP收集1.1.2端口收集1.1.3目录收集 1.2 webs…...

软件分享--智能照片识别分类软件

智能照片识别分类软件&#xff0c;批量识别图片并分类 自动识别照片类型&#xff0c;分为10个类别&#xff1a;车辆、动物、风景、花卉、建筑、街景、美食、人像、夜景、植物、其它 分类准确率90% 本地运行、不需要联网、没有网络也能用、没有注册码、永久使用 如果你拍摄了上…...

Leetcode—409.最长回文串【简单】

2023每日刷题&#xff08;四十八&#xff09; Leetcode—409.最长回文串 强烈吐槽&#xff01;&#xff01;&#xff01; 非常不理解&#xff0c;同样的代码&#xff0c;为什么C跑不了C就跑得了&#xff0c;力扣编译器是对C语言有歧视吗&#xff1f;&#xff1f;&#xff1f;…...

计算机网络入侵检测技术研究

摘 要 随着网络技术的发展&#xff0c;全球信息化的步伐越来越快&#xff0c;网络信息系统己成为一个单位、一个部门、一个行业&#xff0c;甚至成为一个关乎国家国计民生的基础设施&#xff0c;团此&#xff0c;网络安全就成为国防安全的重要组成部分&#xff0c;入侵检测技术…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

android13 app的触摸问题定位分析流程

一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

k8s从入门到放弃之HPA控制器

k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率&#xff08;或其他自定义指标&#xff09;来调整这些对象的规模&#xff0c;从而帮助应用程序在负…...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染&#xff08;SSR&#xff09;与静态网站生成&#xff08;SSG&#xff09; 框架&#xff0c;由 Vercel 开发。它简化了构建生产级 React 应用的过程&#xff0c;并内置了很多特性&#xff1a; ✅ 文件系…...

DAY 45 超大力王爱学Python

来自超大力王的友情提示&#xff1a;在用tensordoard的时候一定一定要用绝对位置&#xff0c;例如&#xff1a;tensorboard --logdir"D:\代码\archive (1)\runs\cifar10_mlp_experiment_2" 不然读取不了数据 知识点回顾&#xff1a; tensorboard的发展历史和原理tens…...