The uniapp WeChat applet introduces threeJs and imports the model

Foreword:

我的需求是使用uniapp写微信小程序,在小程序中使用threeJs就行了,目前暂不考虑兼容app什么的。
1.引入小程序版的threejs库实现
2.使用webview实现(推荐)

focus

My suggestion is to use this library
https://github.com/deepkolos/three-platformize
why? I tried the official library of the small program recommended by uniapp and the threejs-miniprogram , but my obj model could not be loaded. All I recommend not to use the obj model is the best, many of them support the GLTF model, but I can't change it.


The case of using three-platformizethe loaded obj model:
insert image description here
the core code:

html:
<canvas type="webgl" id="webgl" style="width: 100vw; height: 100vh;" 
	@touchstart="touchStart" 
	@touchmove="touchMove" 
	@touchend="touchEnd"
/>
script:
<script>
	import * as THREE from 'three-platformize';
	import {
    
     WechatPlatform } from 'three-platformize/src/WechatPlatform';
	import {
    
     OBJLoader } from 'three-platformize/examples/jsm/loaders/OBJLoader';
	import {
    
     GLTFLoader } from 'three-platformize/examples/jsm/loaders/GLTFLoader';
	import {
    
    OrbitControls} from 'three-platformize/examples/jsm/controls/OrbitControls';
	export default {
    
    
		data() {
    
    
			return {
    
    
				canvas:null,
				camera:null,
				scene:null,
				renderer:null,
				model:null,
				controls:null,
				loopIndex:null
			}
		},
		onLoad() {
    
    

		},
		methods: {
    
    
			async init() {
    
     
				const {
    
     canvas }= await this.getCanvas();
				this.canvas = canvas;
				const platform = new WechatPlatform(canvas); // webgl canvas
				platform.enableDeviceOrientation('game'); // 开启DeviceOrientation
				THREE.PLATFORM.set(platform);
				this.platform = platform;
				this.renderModel();
		    },
			//获取画布
			async getCanvas(delay = 200) {
    
    
			  return new Promise((resolve, reject) => {
				const t = setTimeout(() => {
				  clearTimeout(t);
				  uni.createSelectorQuery().in(this)
					.select('#webgl')
					.fields({ node: true })
					.exec((res) => {
						console.log('res',res)
					  if (res && res[0] && res[0].node) {
						const canvas = res[0].node;
						resolve({ canvas });
					  } else {
						reject("获取canvas失败");
					  }
					});
				}, delay);
			  });
			},
			renderModel () {
				this.camera = new THREE.PerspectiveCamera(45, this.canvas.width / this.canvas.height, 0.25, 100);
				this.camera.position.set(- 5, 3, 10);
				this.camera.lookAt(new THREE.Vector3(0, 2, 0));
				this.scene = new THREE.Scene();
				this.scene.background = new THREE.Color(0xe0e0e0);
				this.scene.fog = new THREE.Fog(0xe0e0e0, 20, 100);
				this.clock = new THREE.Clock();
				// lights
				var light = new THREE.HemisphereLight(0xffffff, 0x444444);
				light.position.set(0, 20, 0);
				this.scene.add(light);
				// 改变外壳颜色
				var AmbientLight = new THREE.AmbientLight(0x815800); // 环境光
				this.scene.add(AmbientLight);
				// 平行光
				light = new THREE.DirectionalLight(0xffffff);
				light.position.set(0, 20, 10);
				this.scene.add(light);
				// // ground
				// var mesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(2000, 2000), new THREE.MeshPhongMaterial({
    
     color: 0x999999, depthWrite: false }));
				// mesh.rotation.x = - Math.PI / 2;
				// this.scene.add(mesh);
				// var grid = new THREE.GridHelper(200, 40, 0x000000, 0x000000);
				// grid.material.opacity = 0.6;
				// grid.material.transparent = true;
				// this.scene.add(grid);
				// model
				var loader = new OBJLoader();
				loader.load('http://localhost:8888/obj3/file.obj', (obj) => {
    
    
					console.log("obj+=")
					console.log(obj)
					// console.log(this.model)
					obj.position.set(0, -2, 0);//模型摆放的位置
					obj.scale.set(0.2, 0.2, 0.2);
					// this.model = obj;
					this.scene.add(obj);
				}, undefined, function (e) {
    
    
					console.log("模型加载错误")
					console.error(e);
				});
				// var loader = new GLTFLoader();
				// 	loader.load('https://dtmall-tel.alicdn.com/edgeComputingConfig/upload_models/1591673169101/RobotExpressive.glb', (gltf) => {
    
    
				// 		this.model = gltf.scene;
				// 		this.scene.add(this.model);
				// 	}, undefined, function (e) {
    
    
				// 		console.error(e);
		  //       });
				// var geometry = new THREE.BoxGeometry( 5, 5, 5 );
				// var material = new THREE.MeshBasicMaterial( {
    
    color: 0x00ff00} );
				// var mesh = new THREE.Mesh( geometry, material );
				// this.scene.add(mesh);
		
				this.renderer = new THREE.WebGLRenderer({
    
    antialias: true });
				this.renderer.setPixelRatio(wx.getSystemInfoSync().pixelRatio);
				this.renderer.setSize(this.canvas.width, this.canvas.height);
				//this.renderer.outputEncoding = true;
				this.renderer.gammaFactor = 2.2;
		
				this.controls = new OrbitControls(this.camera, this.renderer.domElement );
				this.camera.position.set( 5, 5, 10 );
				this.animate();
			},
		animate() {
    
    
		        this.loopIndex = this.canvas.requestAnimationFrame(this.animate);
		        this.renderer.render(this.scene, this.camera);
		        this.controls.update();
		    },
		
		    touchStart(e) {
    
    
		        this.platform.dispatchTouchEvent(e);
		    },
		    touchMove(e) {
    
    
		        this.platform.dispatchTouchEvent(e);
		    },
		    touchEnd(e) {
    
    
		        this.platform.dispatchTouchEvent(e);
		    }
		},
		mounted() {
    
    
			this.$nextTick(()=>  {
    
    
			      this.init();
			    });
		}
	}
</script>

In the above case, two models are used, one obj model, the address of the obj model is the address of the local server written by oneself, which needs to be configured by oneself, and the address of the GLTF model is the network address, which can be viewed by unlocking the annotation.

important point:

1. Loading the external model is consistent with the threeJs official website api.
2. Using this method to load the external model may encounter a situation where the model does not display or WeChat crashes during real machine debugging (the reason is unknown)


Webview implementation introduces threejs library

Effect diagram
insert image description here
Realization:
1. Use vue to implement threejs to import obj model (pc side can be perfectly realized),
2. Introduce the corresponding model display address in webview,

Finished, only these two steps are enough, but I am loading the model dynamically, so when loading the model, you need to pass the value from the applet side to the pc side, so that the pc side loads the corresponding model, here you only need to use get in the address Just pass the parameters in the column.

The following two methods may be used:
1. Model size adaptation

setScaleToFitSize (obj) {
    
    
      const boxHelper = new THREE.BoxHelper(obj);
      boxHelper.geometry.computeBoundingBox();
      const box = boxHelper.geometry.boundingBox;
      const maxDiameter = Math.max((box.max.x - box.min.x), (box.max.y - box.min.y), (box.max.z - box.min.z));
      const scaleValue = camera.position.z / maxDiameter;
      obj.position.set(0, -10, 0);//模型摆放的位置
      obj.scale.set(scaleValue, scaleValue, scaleValue);
      scene.add(obj);
    },

2. Forbid the applet to pull down when displaying the webview: add in
:mounted

document.body.addEventListener('touchmove', function (e) {
    
    
        e.preventDefault();
      }, {
    
     passive: false });

Guess you like

Origin blog.csdn.net/hzqzzz/article/details/126428029