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

ThreeJs功能演示——几何体操作导入导出

1、内部创建几何体导出编辑能力

1)支持内部创建的面、正方体、球体

内部创建物体时,如果是三维物体,要创建集合形状geometry,和对应的材质material。再一起创建一个三维物体。

	// 存储创建的几何体列表const geometries = [];createPlane()createCube()createSphere()addGUIForGeometry(geometries)// 几何体创建函数function createPlane() {const geometry = new THREE.PlaneGeometry(1,1);const material = new THREE.MeshBasicMaterial({color:0xffff00, side:THREE.DoubleSide})const plane = new THREE.Mesh(geometry, material)plane.name = "Plane";plane.position.set(-1, -1, -1)scene.add(plane)geometries.push(plane)return plane;}// 创建正方体function createCube() {const geometry = new THREE.BoxGeometry(1, 1, 1 );const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );const cube = new THREE.Mesh( geometry, material );cube.name = 'Cube';scene.add( cube );geometries.push(cube);return cube;}// 创建球体function createSphere() {const geometry = new THREE.SphereGeometry( 1, 32, 32 );const material = new THREE.MeshBasicMaterial( {color: 0x0000ff} );const sphere = new THREE.Mesh( geometry, material );sphere.name = 'Sphere';sphere.position.set(2,2,2)scene.add( sphere );geometries.push(sphere);return sphere;}

2)支持几何体的位置、角度、比例调整

通过GUI控制器调整创建物体的位置、角度、放大比例信息。

	// GUI控制器function addGUIForGeometry(geometryArr) {const gui = new GUI();gui.add({x:0}, 'x', -10, 10).name('Position X').onChange((value)=>{for (let element of geometryArr) {console.log(element.position)element.position.set(value, element.position.y, element.position.z)}animate()});gui.add({scale:1}, 'scale', 0.1, 10).name('Scale').onChange((value)=>{for (let element of geometryArr) {element.scale.set(value, value, value)}animate()});gui.add({rotateX:0}, "rotateX",  -Math.PI, Math.PI).name("Rotate X").onChange((value)=>{for (let element of geometryArr) {element.rotation.set(value, element.rotation.y, element.rotation.z)}animate()})gui.open();}

3)支持几何体批量导出、重新导入

将3D物体的位置、形状、角度、放大序列化到json文件,支持导出。

导入时,根据物体的类型分别创建3D模型

	// 导入几何体function importGeometries() {const input = document.createElement('input');input.type = 'file';input.accept = '.json';input.addEventListener('change', (event) => {const file = event.target.files[0];if (file) {const reader = new FileReader();reader.onload = (e) => {const geometriesData = JSON.parse(e.target.result);geometriesData.forEach(data => {let geometry;let material;switch (data.type) {case 'Mesh':switch (data.name) {case 'Plane':geometry = new THREE.PlaneGeometry(data.geometryData.vertices, data.geometryData.indices);material = new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.DoubleSide });break;case 'Cube':geometry = new THREE.BoxGeometry(data.geometryData.vertices, data.geometryData.indices);material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });break;case 'Sphere':geometry = new THREE.SphereGeometry(data.geometryData.vertices, data.geometryData.indices);material = new THREE.MeshBasicMaterial({ color: 0x0000ff });break;}const mesh = new THREE.Mesh(geometry, material);mesh.name = data.name;mesh.position.fromArray(data.position);mesh.rotation.fromArray(data.rotation);mesh.scale.fromArray(data.scale);scene.add(mesh);geometries.push(mesh);break;}});};reader.readAsText(file);}});input.click();}

2、整体代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Three.js 几何体操作示例</title><style>body { margin: 0; overflow: hidden; }#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;}</style>
</head>
<body>
<div id="camera-info"></div>
<script type="importmap">{"imports": {"three": "./three.js-master/build/three.module.js","three/addons/": "./three.js-master/examples/jsm/"}}
</script>
<script type="module">import * as THREE from "three"import { OrbitControls } from 'three/addons/controls/OrbitControls.js';import { GUI } from 'three/addons/libs/lil-gui.module.min.js';// 1) 创建画布const scene = new THREE.Scene();scene.background = new THREE.Color( 0xa0a0a0 );const renderer = new THREE.WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 2) 设置 camera 位置,朝向角度const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);camera.position.set(0, 0, 20); // 设置相机位置camera.lookAt(scene.position); // 让相机朝向场景中心// 设置控制轨道const controls = new OrbitControls( camera, renderer.domElement );controls.target.set( 0, 0.1, 0 );controls.update();controls.minDistance = 0.5;controls.maxDistance = 1000;controls.maxPolarAngle = 0.5 * Math.PI;// 5) 支持动态显示摄像头位置、角度、缩放信息const cameraInfo = document.getElementById('camera-info');function updateCameraInfo() {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)}`;}updateCameraInfo();// 渲染循环function animate() {requestAnimationFrame(animate);updateCameraInfo();renderer.render(scene, camera);}animate();// 存储创建的几何体列表const geometries = [];createPlane()createCube()createSphere()addGUIForGeometry(geometries)// 几何体创建函数function createPlane() {const geometry = new THREE.PlaneGeometry(1,1);const material = new THREE.MeshBasicMaterial({color:0xffff00, side:THREE.DoubleSide})const plane = new THREE.Mesh(geometry, material)plane.name = "Plane";plane.position.set(-1, -1, -1)scene.add(plane)geometries.push(plane)return plane;}// 创建正方体function createCube() {const geometry = new THREE.BoxGeometry(1, 1, 1 );const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );const cube = new THREE.Mesh( geometry, material );cube.name = 'Cube';scene.add( cube );geometries.push(cube);return cube;}// 创建球体function createSphere() {const geometry = new THREE.SphereGeometry( 1, 32, 32 );const material = new THREE.MeshBasicMaterial( {color: 0x0000ff} );const sphere = new THREE.Mesh( geometry, material );sphere.name = 'Sphere';sphere.position.set(2,2,2)scene.add( sphere );geometries.push(sphere);return sphere;}// GUI控制器function addGUIForGeometry(geometryArr) {const gui = new GUI();gui.add({x:0}, 'x', -10, 10).name('Position X').onChange((value)=>{for (let element of geometryArr) {console.log(element.position)element.position.set(value, element.position.y, element.position.z)}animate()});gui.add({scale:1}, 'scale', 0.1, 10).name('Scale').onChange((value)=>{for (let element of geometryArr) {element.scale.set(value, value, value)}animate()});gui.add({rotateX:0}, "rotateX",  -Math.PI, Math.PI).name("Rotate X").onChange((value)=>{for (let element of geometryArr) {element.rotation.set(value, element.rotation.y, element.rotation.z)}animate()})gui.open();}function handleKeyDown(event) {switch (event.key) {case 'e':exportToJSON(geometries)break;case 'r':clearGeometries(geometries)break;case 'i':importGeometries(geometries)break;}}document.addEventListener('keydown', handleKeyDown);function exportToJSON(geometryList) {const geometriesData = geometryList.map(geometry => {return {name: geometry.name,position: geometry.position.toArray(),rotation: geometry.rotation.toArray(),scale: geometry.scale.toArray(),// 根据几何体类型添加更多特定信息type: geometry.type,geometryData: geometry.geometry.toJSON()};});const blob = new Blob([JSON.stringify(geometriesData)], { type: 'application/json' });const url = URL.createObjectURL(blob);const a = document.createElement('a');a.href = url;a.download = 'geometries.json';document.body.appendChild(a);a.click();document.body.removeChild(a);URL.revokeObjectURL(url);}// 清除几何体function clearGeometries(geoArr) {geometries.forEach(geometry => scene.remove(geometry));geometries.length = 0;}// 导入几何体function importGeometries() {const input = document.createElement('input');input.type = 'file';input.accept = '.json';input.addEventListener('change', (event) => {const file = event.target.files[0];if (file) {const reader = new FileReader();reader.onload = (e) => {const geometriesData = JSON.parse(e.target.result);geometriesData.forEach(data => {let geometry;let material;switch (data.type) {case 'Mesh':switch (data.name) {case 'Plane':geometry = new THREE.PlaneGeometry(data.geometryData.vertices, data.geometryData.indices);material = new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.DoubleSide });break;case 'Cube':geometry = new THREE.BoxGeometry(data.geometryData.vertices, data.geometryData.indices);material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });break;case 'Sphere':geometry = new THREE.SphereGeometry(data.geometryData.vertices, data.geometryData.indices);material = new THREE.MeshBasicMaterial({ color: 0x0000ff });break;}const mesh = new THREE.Mesh(geometry, material);mesh.name = data.name;mesh.position.fromArray(data.position);mesh.rotation.fromArray(data.rotation);mesh.scale.fromArray(data.scale);scene.add(mesh);geometries.push(mesh);break;}});};reader.readAsText(file);}});input.click();}
</script>
</body>
</html>

http://www.lryc.cn/news/522002.html

相关文章:

  • LeetCode::2270. 分割数组的方案数
  • elementui表单验证,数据层级过深验证失效
  • 【Java】LinkedHashMap (LRU)淘汰缓存的使用
  • CancerGPT :基于大语言模型的罕见癌症药物对协同作用少样本预测研究
  • 《汽车维护与修理》是什么级别的期刊?是正规期刊吗?能评职称吗?
  • tomcat状态一直是Exited (1)
  • 消息中间件的基础概念入门
  • 基于Web的宠物医院看诊系统设计与实现(源码+定制+开发)在线预约平台、宠物病历管理、医生诊疗记录、宠物健康数据分析 宠物就诊预约、病历管理与健康分析
  • Excel数据叠加生成新DataFrame:操作指南与案例
  • Web 开发入门之旅:从静态页面到全栈应用的第一步
  • WebSocket实现分布式的不同方案对比
  • 基于注意力机制的端到端合成语音检测
  • MySQL NaviCat 安装及配置教程(Windows)【安装】
  • 微信小程序:播放音频
  • Ubuntu安装K8S
  • 独立同分布时,联合概率密度函数等于边缘概率密度函数乘积
  • 半导体数据分析: 玩转WM-811K Wafermap 数据集(三) AI 机器学习
  • 【.net core】【sqlsugar】时间查询示例
  • Kotlin 协程基础十 —— 协作、互斥锁与共享变量
  • Java中网络编程的学习
  • [计算机网络]一. 计算机网络概论第一部分
  • 【0393】Postgres内核 checkpointer process ③ 构建 WAL records 工作缓存区
  • 正则表达式基础知识及grep、sed、awk常用命令
  • redhat安装docker 24.0.7
  • 【excel】VBA简介(Visual Basic for Applications)
  • 【大厂面试AI算法题中的知识点】方向涉及:ML/DL/CV/NLP/大数据...本篇介绍为什么self-attention可以堆叠多层,这有什么作用?
  • NanoKVM简单开箱测评和拆解,让普通电脑实现BMC/IPMI远程管理功能
  • 【Idea】编译Spring源码 read timeout 问题
  • VSCode的配置与使用(C/C++)
  • SpringMVC (1)