项目使用到3D模型加载渲染,故初学习了解之,
简单封装 代码如下
import * as THREE from "three";
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
import {ShaderPass} from "three/examples/jsm/postprocessing/ShaderPass";
import {FXAAShader} from "three/examples/jsm/shaders/FXAAShader";
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader";
import {DRACOLoader} from "three/examples/jsm/loaders/DRACOLoader";
import {EffectComposer} from "three/examples/jsm/postprocessing/EffectComposer";
import {RenderPass} from "three/examples/jsm/postprocessing/RenderPass";
import {OutlinePass} from "three/examples/jsm/postprocessing/OutlinePass";
class ThreeJsLoder {
constructor(ref) {
this.webglRef = ref;
this.canvasSetting = {width: 960, height: 500}
this.camera = new THREE.PerspectiveCamera(50, this.canvasSetting.width / this.canvasSetting.height, 1, 2000);
this.renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
this.HemisphereLight = new THREE.HemisphereLight(0xffffff, 0xaaaaaa, 1);
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.scene = new THREE.Scene();
this.devices = [];
this.rayCaster = new THREE.Raycaster();
this.effectFXAA = new ShaderPass(FXAAShader);
this.gltfLoader = new GLTFLoader();
this.dracoLoader = new DRACOLoader();
this.dracoLoader.setDecoderPath("/draco/");
this.dracoLoader.setDecoderConfig({type: 'js'});
this.gltfLoader.setDRACOLoader(this.dracoLoader);
this.composer = null;
}
loadModel(link, eleId, onSuccess, onProgress, onError) {
this.clear();
this.gltfLoader.load(link, (gltf) => {
gltf.scene.position.set(0, 20, 0);
gltf.scene.scale.set(2.2, 2.2, 2.2);
this.camera.position.set(10, 80, -80);
this.scene.add(gltf.scene)
this.scene.add(this.HemisphereLight);
this.scene.add(this.camera);
this.renderer.setClearColor(new THREE.Color(0x000000));
this.renderer.setSize(this.canvasSetting.width, this.canvasSetting.height);
this.webglRef.appendChild(this.renderer.domElement);
this.controls.addEventListener('change', () => {
this.renderer.render(this.scene, this.camera)
});
this.controls.autoRotateSpeed = 1.5;
this.controls.target.set(0, 0, 0);
this.controls.update();
this.renderer.render(this.scene, this.camera);
gltf.scene.traverse((r) => {
if (r instanceof THREE.Mesh) {
this.devices.push(r);
}
});
if (onSuccess) {
onSuccess();
}
}, (xhr) => {
if (onProgress) {
let percentComplete = null;
if (xhr.lengthComputable) {
percentComplete = xhr.loaded / xhr.total * 100;
}
onProgress(xhr, percentComplete);
}
}, (e) => {
if (onError) {
onError(e);
}
});
}
getChoose(event) {
let x = (event.offsetX / this.canvasSetting.width) * 2 - 1;
let y = -(event.offsetY / this.canvasSetting.height) * 2 + 1;
this.rayCaster.setFromCamera(new THREE.Vector2(x, y), this.camera);
let intersects = this.rayCaster.intersectObjects(this.devices);
let mesh = false;
if (intersects.length > 0) {
mesh = intersects[0].object;
this.outlineObj(mesh)
} else {
this.renderer.render(this.scene, this.camera);
}
return mesh;
}
outlineObj(obj) {
if (obj) {
this.composer = new EffectComposer(this.renderer);
const renderPass = new RenderPass(this.scene, this.camera);
this.composer.addPass(renderPass);
const outlinePass = new OutlinePass(
new THREE.Vector2(this.canvasSetting.width, this.canvasSetting.height),
this.scene,
this.camera
);
outlinePass.selectedObjects = [obj];
outlinePass.edgeStrength = 30.0;
outlinePass.edgeGlow = 0;
outlinePass.usePatternTexture = false;
outlinePass.edgeThickness = 3.0;
outlinePass.downSampleRatio = 1;
outlinePass.pulsePeriod = 1;
outlinePass.visibleEdgeColor.set(parseInt(0xff6347));
outlinePass.hiddenEdgeColor = new THREE.Color(0, 0, 0);
outlinePass.clear = true;
this.composer.addPass(outlinePass);
this.effectFXAA.uniforms["resolution"].value.set(
1 / window.innerWidth,
1 / window.innerHeight
);
this.effectFXAA.renderToScreen = true;
this.composer.addPass(this.effectFXAA);
this.composer.render()
} else {
this.composer = null;
}
}
clear() {
this.devices.splice(0, this.devices.length);
this.scene.clear();
this.camera.clear();
this.renderer.clear();
this.controls.update();
this.renderer.render(this.scene, this.camera)
this.webglRef.innerHTML = " ";
}
}
export {ThreeJsLoder}
obj2gltf -i luyu.obj -o luyu.gltf
gltf-pipeline -i luyu.gltf -o out.gltf -d
vue2.x 使用
1.node_modules文件下 找到three文件夹, 找到/examples/js/libs/draco/ 将draco整个文件夹复制到public路径下
2.threeJS中的渲染对象 不可用vue的数据方向绑定,会造成卡顿
<template>
<div v-loading="!webglShow">
<div
id="webgl"
ref="webgl"
@click="clickEvent"
></div>
</div>
</template>
<script>
import {ThreeJsLoder} from "@/utils/ModelConfig/ThreeJsLoder";
let threeJsLoder;
export default {
props: ["modelForm"],
name: "ModelConfig",
data() {
return {
webglShow: false,
mesh: {},
}
},
mounted() {
this.init({link:"压缩gltf的路径地址"});
},
methods: {
init(item) {
modelConfig = new ThreeJsLoder(this.$refs.webgl);
modelConfig.loadModel(item.link,()=>{
this.webglShow = true;
})
},
clickEvent(event) {
this.mesh = modelConfig.getChoose(event);
if(this.mesh){
console.log(this.mesh);
}
},
};
</script>
<style scoped>
</style>
效果如图,
![在这里插入图片描述](https://img-blog.csdnimg.cn/26ec9deec9ff4640b01553b798d9dc51.png)
参考
Threejs大型obj文件的秒加载实现
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)