技术标签: three.js问题 3d模型可视化编辑器 three.js性能优化 Three.js three.js问题总结 three.js
(1) 确保当前文件内容是否能被读取,在Javascript的console中查找错误,并确定当你调用.load()的时候,使用了onError回调函数来输出结果, 如果err 输出则表示当前glb 文件内容无法被读取从新换一个glb文件尝试
const loader = new GLTFLoader()
loader.load('/three/1.glb', (result) => {
console.log(result)
}, () => {
}, (err) => {
console.log(err)
})
(2) 尝试将模型放大或缩小到原来的1000倍。许多模型的缩放比例各不相同,如果摄像机位于模型内,则大型模型将可能不会显示。或者可以在模型加载完成之后根据模型比例大小设置合适的缩放值
//设置模型位置
this.model.updateMatrixWorld()
const box = new THREE.Box3().setFromObject(this.model);
const size = box.getSize(new THREE.Vector3());
const center = box.getCenter(new THREE.Vector3());
// 计算缩放比例
const maxSize = Math.max(size.x, size.y, size.z);
const targetSize = 2.5; // 目标大小
const scale = targetSize / (maxSize > 1 ? maxSize : .5);
this.model.scale.set(scale, scale, scale)
// 设置控制器最小缩放值
this.controls.maxDistance = size.length() * 10
// 设置相机位置
this.camera.position.set(0, 2, 6)
// 设置相机坐标系
this.camera.lookAt(center)
this.camera.updateProjectionMatrix();
(3)增加相机远端面的值 far,如果在创建相机时摄像机视锥体远端面的值设置过小也无法蒋模型正确的显示出来
this.camera = new THREE.PerspectiveCamera(45, clientWidth / clientHeight, 0.25, 100)
this.camera.far = 2000
this.camera.updateProjectionMatrix()
(4) 尝试添加一个光源并改变其位置。模型或许被隐藏在黑暗中。
// 创建一个平行光
this.directionalLight = new THREE.DirectionalLight('#1E90FF', 1)
this.directionalLight.position.set(-1.44, 2.2, 1)
this.directionalLight.castShadow = true
this.scene.add(this.directionalLight)
(1)在场景动画帧渲染中对背景图进行单独处理
sceneAnimation() {
this.renderAnimation = requestAnimationFrame(() => this.sceneAnimation())
// 将不需要处理辉光的材质进行存储备份
this.scene.traverse((v) => {
if (v instanceof THREE.Scene) {
this.materials.scene = v.background
v.background = null
}
if (!this.glowMaterialList.includes(v.name) && v.isMesh) {
this.materials[v.uuid] = v.material
v.material = new THREE.MeshBasicMaterial({
color: 'black' })
}
})
this.glowComposer.render()
// 在辉光渲染器执行完之后在恢复材质原效果
this.scene.traverse((v) => {
if (this.materials[v.uuid]) {
v.material = this.materials[v.uuid]
delete this.materials[v.uuid]
}
if (v instanceof THREE.Scene) {
v.background = this.materials.scene
delete this.materials.scene
}
})
this.effectComposer.render()
}
在窗口监听方法中更新相机,渲染器等相关信息
window.addEventListener("resize", this.onWindowResize.bind(this))
// 监听窗口变化
onWindowResize() {
const {
clientHeight, clientWidth } = this.container
//调整屏幕大小
this.camera.aspect = clientWidth / clientHeight //摄像机宽高比例
this.camera.updateProjectionMatrix() //相机更新矩阵,将3d内容投射到2d面上转换
this.renderer.setSize(clientWidth, clientHeight)
this.effectComposer.setSize(clientWidth, clientHeight)
this.glowComposer.setSize(clientWidth, clientHeight)
}
模型材质类型为 Mesh 的材质支持修改 position
const mesh = this.model.getObjectByName(name)
if(mesh.type == 'Mesh){
mesh.position.set(1,10,1)
}
three.js支持 修改网格,透明渡和颜色的材质有:
MeshBasicMaterial,MeshLambertMaterial,MeshPhongMaterial,MeshStandardMaterial,MeshPhysicalMaterial,MeshToonMaterial 这六种
// 启用或禁用摄像机平移,默认为true。
this.controls.enablePan = false
// 当设置为false时,控制器将不会响应用户的操作。默认值为true。
thsi.controls.enabled =false
// 启用或禁用摄像机水平或垂直旋转。默认值为true。
thsi.controls.enableRotate =false
// 启用或禁用摄像机的缩放。
thsi.controls.enableZoom =false
const colot = new THREE.Color(colorRGB).getStyle()
将 frustumCulled值设置为false不管是否在相机视椎体都会渲染
this.model.traverse(item => {
if (item.isMesh && item.material) {
item.frustumCulled = false
}
})
可能原因有以下几种:
1.文件资源在项目本地文件夹public(vue项目)
2.服务器未提供 Content-Length: 服务器在响应头中未提供正确的 Content-Length 字段,或者提供的值无效。在这种情况下,浏览器无法确定要加载的总字节数,因此 lengthComputable 被设置为 false
3.流式传输: 一些加载场景中,数据是通过流式传输的方式加载的,因此无法预先知道要加载的总字节数。例如,通过 WebSocket 或 SSE (Server-Sent Events) 加载数据时,通常无法确定总字节数。
lengthComputable 为false 情况单独处理 :
onModelProgress(progressEvent ){
const {
loaded ,total ,lengthComputable } = progressEvent
//lengthComputable true 可以获取到当前文件的总字节大小
if(lengthComputable ){
const progress = loaded / total * 100
console.log( progress + '% loaded' )
}else{
console.log('已加载'+loaded+'字节' )
}
}
在需要把当前场景的内容导出为一个glb或者gltf文件时,使用 GLTFExporter方法对场景进行导出,在导出来新的glb文件时发现原来的模型文件的动画丢失了
解决方法: three.js GLTFExporter 方法的第三个参数提供 导出相关配置的传入 options , 获取到当前场景需要的导出的剪辑动画 animations 在调用导出方法时传入即可。
代码如下示例: 注意是GLTFExporter 的第三个参数,第二个参数为 导出错误的回调函数
const type = 'glb'
const exporter = new GLTFExporter();
const options = {
trs: true, // 是否保留位置、旋转、缩放信息
animations: this.modelAnimation, // 导出的动画
binary: type == 'glb' ? true : false, // 是否以二进制格式输出
embedImages: true,//是否嵌入贴图
onlyVisible: true, //是否只导出可见物体展
}
exporter.parse(this.scene, function (result) {
if (result instanceof ArrayBuffer) {
// 将结果保存为GLB二进制文件
saveArrayBuffer(result, `${
new Date().toLocaleString()}.glb`);
} else {
// 将结果保存为GLTF JSON文件
saveString(JSON.stringify(result), `${
new Date().toLocaleString()}.gltf`);
}
function saveArrayBuffer(buffer, filename) {
// 将二进制数据保存为文件
const blob = new Blob([buffer], {
type: 'application/octet-stream' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.click();
URL.revokeObjectURL(url);
console.log('导出成功')
}
function saveString(text, filename) {
// 将字符串数据保存为文件
const blob = new Blob([text], {
type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.click();
URL.revokeObjectURL(url);
console.log('导出成功')
}
}, (err) => {
console.log('导出错误',err)
}, options);
在页面关闭销毁和跳转离开时清除代码中 定时器,事件监听 和动画帧等相关方法。释放场景中的材质内存,清除场景和模型相关信息
// 清除模型数据
onClearModelData(){
cancelAnimationFrame(this.rotationAnimationFrame)
cancelAnimationFrame(this.renderAnimation)
cancelAnimationFrame(this.animationFrame)
this.container.removeEventListener('click', this.onMouseClickModel)
this.container.removeEventListener('mousedown', this.onMouseDownModel)
this.container.removeEventListener('mousemove', this.onMouseMoveModel)
window.removeEventListener("resize", this.onWindowResize)
// 材质释放内存
this.scene.traverse((v) => {
if (v.type === 'Mesh') {
v.geometry.dispose();
v.material.dispose();
}
})
// 清除场景和模型相关信息
this.model.clear()
this.scene.clear()
}
文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99
文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效
文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是
文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件
文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件
文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码
文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware
文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停
文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待
文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析
文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code
文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象