微信小程序使用ThreeX开发3d

注意:本代码是用uniapp开发微信小程序,模型使用.glb格式,以下出现(glb模型压缩)代表改代码是使用压缩时需要使用的,不压缩可以不写

Demo:gitee地址  焦明玉/vue2_threex_demo

1.微信小程序后台添加Threex插件

2.manifest.json

/* 小程序特有相关 */
	"mp-weixin": {
		"appid": "wx3402c0e00773fc5a",
		"setting": {
			"urlCheck": false,
			"es6": true, // glb模型压缩
			"minified": false
		},
		"usingComponents": true,
		"workers": { // glb模型压缩
			"path": "workers",
			"isSubpackage": true
		},
		"plugins": {
			"ThreeX": {
				"version": "3.1.0",
				"provider": "wx5d6376b4fc730db9",
				"export": "threex.js"
			}
		}
	},

3.threex.js

module.exports = {
	getApp() {
		return getApp()
	},
	getCurrentPages() {
		return getCurrentPages()
	},
	wx_downloadFile() {
		return wx.downloadFile
	},
	wx_request() {
		return wx.request
	}
}

 

4.vue.config.js.js (glb模型压缩)


const path = require('path');

module.exports = {
	configureWebpack: {
		devServer: {
			disableHostCheck: true
		},
		resolve: {
			alias: {
				'@workers': path.resolve(__dirname, 'workers')
			}
		}
	},
	chainWebpack: config => {
		config.module
			.rule('js')
			.include
			.add(path.resolve(__dirname, 'workers'))
			.end()
			.use('babel-loader')
			.loader('babel-loader')
			.tap(options => {
				// modify the options...
				return options;
			});
	}
};

5.workers目录放置在根目录与pages同级(glb模型压缩)

6.jsm_weixin目录放置在pages下

7.页面使用

<template>
	<view id="page">
		<canvas id="canvas_webgl2" type="webgl2" @touchstart="webgl_touch" @touchmove="webgl_touch"
			@touchend="webgl_touch" @touchcancel="webgl_touch">
		</canvas>
	</view>
</template>

<script>
	const THREE = requirePlugin("ThreeX")
	const {
		document,
		window,
		HTMLCanvasElement,
		requestAnimationFrame,
		cancelAnimationFrame,
		core,
		Event,
		Event0
	} = THREE.DHTML
	import {
		OrbitControls
	} from '../jsm_weixin/controls/OrbitControls.js';
	import {
		OrbitControls0
	} from '../jsm_weixin/controls/OrbitControls0.js';
	import {
		GLTFLoader
	} from '../jsm_weixin/loaders/GLTFLoader.js';
	import {
		DRACOLoader
	} from '../jsm_weixin/loaders/DRACOLoader.js'; // glb模型压缩
	let requestId;

	export default {
		data() {
			return {
				canvas: {},
				renderer: {},
			}
		},
		onUnload() {
			cancelAnimationFrame(requestId, this.canvas)
			this.worker && this.worker.terminate()
			if (this.canvas) this.canvas = null
			setTimeout(() => {
				if (this.renderer instanceof THREE.WebGLRenderer) {
					this.renderer.dispose()
					this.renderer.forceContextLoss()
					this.renderer.context = null
					this.renderer.domElement = null
					this.renderer = null
				}
			}, 10)
		},
		onLoad() {
			uni.showLoading({
				title: '模型加载中...',
				mask: true
			})
			document.createElementAsync("canvas", 'webgl2', this).then(canvas => {
				this.canvas = canvas
				this.run(canvas).then()
			})
		},
		methods: {
			// 手指事件
			webgl_touch(e) {
				const web_e = (window.platform == "devtools" ? Event : Event0).fix(e)
				this.canvas.dispatchEvent(web_e)
			},
			// 初始化渲染模型
			async run(canvas) {
				// 渲染器
				this.renderer = new THREE.WebGLRenderer({
					antialias: true,
					canvas
				});
				this.renderer.setPixelRatio(window.devicePixelRatio);
				this.renderer.setSize(window.innerWidth, window.innerHeight);
				this.renderer.outputEncoding = THREE.sRGBEncoding;
				// 场景
				let scene = new THREE.Scene();
				scene.background = new THREE.Color(0xe7e5e0);
				// 相机
				let camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 100);
				camera.position.set(7, 7, 7);
				camera.lookAt(scene.position);
				// 控制器
				const controls = new(window.platform == "devtools" ? OrbitControls : OrbitControls0)(camera, this
					.renderer.domElement);
				controls.enablePan = true;
				controls.enableZoom = true;
				controls.update();
				// 坐标系	x轴:红色;Y轴:绿色;Z轴:蓝色
				// let axes = new THREE.AxesHelper(5);
				// scene.add(axes);
				// 环境光
				const light0 = new THREE.AmbientLight(0xf7f7dd, 1);
				scene.add(light0);
				// 平行光
				// 平行光源1	头,右
				const dLight1 = new THREE.DirectionalLight(0xFFFFFF, 0.5);
				dLight1.position.set(5, 0, 10);
				scene.add(dLight1);
				// 平行光源2	顶,左,后(补充光)
				const dLight2 = new THREE.DirectionalLight(0xFFFFFF, 0.5);
				dLight2.position.set(-3, 5, 10);
				scene.add(dLight2);
				// 平行光源3	后,左
				const dLight3 = new THREE.DirectionalLight(0xFFFFFF, 0.5);
				dLight3.position.set(-5, 0, -10);
				scene.add(dLight3);

				// 加载模型
				// let dracoLoader = new DRACOLoader(); // glb模型压缩
				// dracoLoader.setDecoderPath('jsm/libs/draco/gltf/');  // glb模型压缩
				let loader = new GLTFLoader();
				// loader.setDRACOLoader(dracoLoader);  // glb模型压缩
				// 压缩:https://zxgj.sxgokit.com:8443/profile/static/3d/3dmodel/3dmodel/DRACO_Car.glb
				// 贴图处理:https://zxgj.sxgokit.com:8443/profile/static/3d/3dmodel/3dmodel/car1.glb
				loader.load(
					'https://zxgj.sxgokit.com:8443/profile/static/3d/3dmodel/3dmodel/car1.glb',
					function(gltf) {
						gltf.scene.position.set(0, 1.5, -0.5);
						gltf.scene.scale.set(1.5, 1.5, 1.5);
						scene.add(gltf.scene);
						uni.hideLoading()
					},
					null,
					function(e) {
						uni.hideLoading();
						uni.showToast({
							title: '模型加载失败!',
							icon: 'none'
						})
						console.error(e);
					}
				);

				// 动画及渲染
				const animate = () => {
					requestAnimationFrame(() => {
						animate();
					});
					this.renderer.render(scene, camera);
				};
				animate();
			},
		}
	}
</script>
<style scoped>
	page,
	canvas {
		overflow: hidden;
		width: 100%;
		height: 100vh;
		background-color: #caeeef;
	}
</style>

接下来说一下我遇到的问题:

1.模型加载贴图丢失,贴图太大了最好每张图不超过2kb,1kb最好。使用压缩可以正常显示,但是压缩会引进来约500kbjs代码

2.千万记得模板不要动,不要动,不要动。(模板有问题canvas会报错)下面的js可以修改

3.使用了压缩没有开启es6转es5会报错$gwx啥

4.这玩意儿很耗模拟器内存,模型体积越小越好,太大可能会加载不出来或者出现贴图丢失,模型渲染出来就是黑色

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只大菜鸟J

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值