├── example ├── pages │ ├── pano │ │ ├── pano.wxss │ │ ├── pano.json │ │ ├── pano.wxml │ │ └── pano.js │ └── index │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ └── index.js ├── textures │ ├── UV_Grid_Sm.jpg │ ├── skybox │ │ ├── nx.jpg │ │ ├── ny.jpg │ │ ├── nz.jpg │ │ ├── px.jpg │ │ ├── py.jpg │ │ └── pz.jpg │ └── fisheye │ │ └── pano2048-1024.jpg ├── README.md ├── sitemap.json ├── app.js ├── app.wxss ├── app.json └── project.config.json ├── pano-littlePlanet.mp4 └── README.md /example/pages/pano/pano.wxss: -------------------------------------------------------------------------------- 1 | /* pages/pano/pano.wxss */ -------------------------------------------------------------------------------- /example/pages/index/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } -------------------------------------------------------------------------------- /pano-littlePlanet.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leo9960/xcx_threejs/HEAD/pano-littlePlanet.mp4 -------------------------------------------------------------------------------- /example/textures/UV_Grid_Sm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leo9960/xcx_threejs/HEAD/example/textures/UV_Grid_Sm.jpg -------------------------------------------------------------------------------- /example/textures/skybox/nx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leo9960/xcx_threejs/HEAD/example/textures/skybox/nx.jpg -------------------------------------------------------------------------------- /example/textures/skybox/ny.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leo9960/xcx_threejs/HEAD/example/textures/skybox/ny.jpg -------------------------------------------------------------------------------- /example/textures/skybox/nz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leo9960/xcx_threejs/HEAD/example/textures/skybox/nz.jpg -------------------------------------------------------------------------------- /example/textures/skybox/px.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leo9960/xcx_threejs/HEAD/example/textures/skybox/px.jpg -------------------------------------------------------------------------------- /example/textures/skybox/py.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leo9960/xcx_threejs/HEAD/example/textures/skybox/py.jpg -------------------------------------------------------------------------------- /example/textures/skybox/pz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leo9960/xcx_threejs/HEAD/example/textures/skybox/pz.jpg -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | 目前测试小程序的WebGL发现有三个扩展不支持: 2 | WEBGL_depth_texture 3 | ANGLE_instanced_arrays 4 | OES_texture_float_linear -------------------------------------------------------------------------------- /example/pages/pano/pano.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {}, 3 | "pageOrientation": "auto", 4 | "navigationStyle":"custom" 5 | } -------------------------------------------------------------------------------- /example/textures/fisheye/pano2048-1024.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leo9960/xcx_threejs/HEAD/example/textures/fisheye/pano2048-1024.jpg -------------------------------------------------------------------------------- /example/sitemap.json: -------------------------------------------------------------------------------- 1 | { 2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", 3 | "rules": [{ 4 | "action": "allow", 5 | "page": "*" 6 | }] 7 | } -------------------------------------------------------------------------------- /example/app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | var THREE=require("./utils/three.js"); 3 | App({ 4 | THREE: THREE, 5 | PANOLENS:require("./utils/panolens.js"), 6 | SystemInfo:wx.getSystemInfoSync(), 7 | onLaunch: function () { 8 | }, 9 | }) -------------------------------------------------------------------------------- /example/app.wxss: -------------------------------------------------------------------------------- 1 | /**app.wxss**/ 2 | .container { 3 | height: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | justify-content: space-between; 8 | padding: 200rpx 0; 9 | box-sizing: border-box; 10 | } 11 | -------------------------------------------------------------------------------- /example/pages/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | "pages/pano/pano", 4 | "pages/index/index" 5 | ], 6 | "window": { 7 | "backgroundTextStyle": "light", 8 | "navigationBarBackgroundColor": "#fff", 9 | "navigationBarTitleText": "WeChat", 10 | "navigationBarTextStyle": "black" 11 | }, 12 | "sitemapLocation": "sitemap.json" 13 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xcx_threejs 2 | 基于three.js r97改造 3 | 4 | 在小程序中直接引入 5 | 6 | var THREE=require("three.js") 7 | 8 | 即可使用 9 | 10 | ### 关于Texture的加载 11 | 12 | 目前推荐使用TextureLoader.load(canvas,path)方式加载,或者可以另外创建一个Canvas,将图片通过drawImage画上去,再用wx.canvasGetImageData获取像素点数据传入DataTexture(data,width,height) 13 | 14 | ##### 有任何建议可以在issue中随意发表,毕竟这个只是刚开始,各位也可以按照思路自行把用到的方法改造到可用 15 | -------------------------------------------------------------------------------- /example/pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | /**index.wxss**/ 2 | .userinfo { 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | } 7 | 8 | .userinfo-avatar { 9 | width: 128rpx; 10 | height: 128rpx; 11 | margin: 20rpx; 12 | border-radius: 50%; 13 | } 14 | 15 | .userinfo-nickname { 16 | color: #aaa; 17 | } 18 | 19 | .usermotto { 20 | margin-top: 200px; 21 | } -------------------------------------------------------------------------------- /example/pages/pano/pano.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | cameraP:{{camera.position.x}} {{camera.position.y}} {{camera.position.z}} 5 | cameraR:{{camera.rotation._x}} {{camera.rotation._y}} {{camera.rotation._z}} 6 | cameraFOV:{{camera.fov}} currentorientation:{{currentorientation||0}} 7 | -------------------------------------------------------------------------------- /example/project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件", 3 | "packOptions": { 4 | "ignore": [] 5 | }, 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": false, 9 | "postcss": true, 10 | "minified": false, 11 | "newFeature": true, 12 | "autoAudits": false, 13 | "checkInvalidKey": true 14 | }, 15 | "compileType": "miniprogram", 16 | "libVersion": "2.7.0", 17 | "appid": "wx6a49b22c4ffaa131", 18 | "projectname": "threejsTest", 19 | "debugOptions": { 20 | "hidedInDevtools": [] 21 | }, 22 | "isGameTourist": false, 23 | "simulatorType": "wechat", 24 | "simulatorPluginLibVersion": {}, 25 | "condition": { 26 | "search": { 27 | "current": -1, 28 | "list": [] 29 | }, 30 | "conversation": { 31 | "current": -1, 32 | "list": [] 33 | }, 34 | "game": { 35 | "currentL": -1, 36 | "list": [] 37 | }, 38 | "miniprogram": { 39 | "current": -1, 40 | "list": [] 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /example/pages/index/index.js: -------------------------------------------------------------------------------- 1 | //index.js 2 | //获取应用实例 3 | var app=getApp(); 4 | var THREE = app.THREE 5 | var requestAnimationFrame; 6 | var camera, scene, renderer; 7 | var mouseX = 0, mouseY = 0; 8 | var windowHalfX = 0; 9 | var windowHalfY = 0; 10 | 11 | Page({ 12 | data: { 13 | }, 14 | onLoad: function () { 15 | this.setData({ 16 | canvasWidth: app.SystemInfo.windowWidth * app.SystemInfo.pixelRatio, 17 | canvasHeight: app.SystemInfo.windowHeight * app.SystemInfo.pixelRatio, 18 | canvasStyleWidth: app.SystemInfo.windowWidth + "px", 19 | canvasStyleHeight: app.SystemInfo.windowHeight + "px", 20 | }); 21 | }, 22 | onReady:function(){ 23 | var self = this; 24 | var query = wx.createSelectorQuery().select('#webgl').node().exec((res) => { 25 | var canvas = res[0].node; 26 | requestAnimationFrame = canvas.requestAnimationFrame; 27 | canvas.width = canvas._width; 28 | canvas.height = canvas._height; 29 | canvas.style = {}; 30 | canvas.style.width = canvas.width; 31 | canvas.style.height = canvas.height; 32 | self.init(canvas); 33 | self.animate(); 34 | }) 35 | }, 36 | init: function (canvas) { 37 | var self = this; 38 | windowHalfX = canvas.width/2; 39 | windowHalfY = canvas.height/2; 40 | camera = new THREE.PerspectiveCamera(20, canvas.width / canvas.height, 1, 10000); 41 | camera.position.z = 1800; 42 | scene = new THREE.Scene(); 43 | scene.background = new THREE.Color(0xffffff); 44 | var light = new THREE.DirectionalLight(0xffffff); 45 | light.position.set(0, 0, 1); 46 | scene.add(light); 47 | // shadow 48 | var shadowTexture = new THREE.TextureLoader().load(canvas,'../../textures/UV_Grid_Sm.jpg'); 49 | var shadowMaterial = new THREE.MeshBasicMaterial({ map: shadowTexture }); 50 | var shadowGeo = new THREE.PlaneBufferGeometry(300, 300, 1, 1); 51 | var shadowMesh; 52 | shadowMesh = new THREE.Mesh(shadowGeo, shadowMaterial); 53 | shadowMesh.position.y = - 250; 54 | shadowMesh.rotation.x = - Math.PI / 2; 55 | scene.add(shadowMesh); 56 | shadowMesh = new THREE.Mesh(shadowGeo, shadowMaterial); 57 | shadowMesh.position.y = - 250; 58 | shadowMesh.position.x = - 400; 59 | shadowMesh.rotation.x = - Math.PI / 2; 60 | scene.add(shadowMesh); 61 | shadowMesh = new THREE.Mesh(shadowGeo, shadowMaterial); 62 | shadowMesh.position.y = - 250; 63 | shadowMesh.position.x = 400; 64 | shadowMesh.rotation.x = - Math.PI / 2; 65 | scene.add(shadowMesh); 66 | var radius = 200; 67 | var geometry1 = new THREE.IcosahedronBufferGeometry(radius, 1); 68 | var count = geometry1.attributes.position.count; 69 | geometry1.addAttribute('color', new THREE.BufferAttribute(new Float32Array(count * 3), 3)); 70 | var geometry2 = geometry1.clone(); 71 | var geometry3 = geometry1.clone(); 72 | var color = new THREE.Color(); 73 | var positions1 = geometry1.attributes.position; 74 | var positions2 = geometry2.attributes.position; 75 | var positions3 = geometry3.attributes.position; 76 | var colors1 = geometry1.attributes.color; 77 | var colors2 = geometry2.attributes.color; 78 | var colors3 = geometry3.attributes.color; 79 | for (var i = 0; i < count; i++) { 80 | color.setHSL((positions1.getY(i) / radius + 1) / 2, 1.0, 0.5); 81 | colors1.setXYZ(i, color.r, color.g, color.b); 82 | color.setHSL(0, (positions2.getY(i) / radius + 1) / 2, 0.5); 83 | colors2.setXYZ(i, color.r, color.g, color.b); 84 | color.setRGB(1, 0.8 - (positions3.getY(i) / radius + 1) / 2, 0); 85 | colors3.setXYZ(i, color.r, color.g, color.b); 86 | } 87 | var material = new THREE.MeshPhongMaterial({ 88 | color: 0xffffff, 89 | flatShading: true, 90 | vertexColors: THREE.VertexColors, 91 | shininess: 0 92 | }); 93 | var wireframeMaterial = new THREE.MeshBasicMaterial({ color: 0x000000, wireframe: true, transparent: true }); 94 | var mesh = new THREE.Mesh(geometry1, material); 95 | var wireframe = new THREE.Mesh(geometry1, wireframeMaterial); 96 | mesh.add(wireframe); 97 | mesh.position.x = - 400; 98 | mesh.rotation.x = - 1.87; 99 | scene.add(mesh); 100 | var mesh = new THREE.Mesh(geometry2, material); 101 | var wireframe = new THREE.Mesh(geometry2, wireframeMaterial); 102 | mesh.add(wireframe); 103 | mesh.position.x = 400; 104 | scene.add(mesh); 105 | var mesh = new THREE.Mesh(geometry3, material); 106 | var wireframe = new THREE.Mesh(geometry3, wireframeMaterial); 107 | mesh.add(wireframe); 108 | scene.add(mesh); 109 | renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true }); 110 | }, 111 | animate:function() { 112 | requestAnimationFrame(this.animate); 113 | this.render(); 114 | }, 115 | render: function () { 116 | camera.position.x += (mouseX - camera.position.x) * 0.05; 117 | camera.position.y += (- mouseY - camera.position.y) * 0.05; 118 | camera.lookAt(scene.position); 119 | renderer.render(scene, camera); 120 | }, 121 | onTouchStart: function (event){ }, 122 | onTouchMove:function (event) { 123 | mouseX = (event.touches[0].clientX - windowHalfX); 124 | mouseY = (event.touches[0].clientY - windowHalfY); 125 | }, 126 | onTouchEnd: function (event) { }, 127 | }) 128 | -------------------------------------------------------------------------------- /example/pages/pano/pano.js: -------------------------------------------------------------------------------- 1 | // pages/pano/pano.js 2 | var app = getApp(); 3 | var THREE = app.THREE; 4 | var PANOLENS = app.PANOLENS; 5 | var pl; 6 | var requestAnimationFrame, cancelAnimationFrame; 7 | var panorama, viewer; 8 | 9 | Page({ 10 | data: { 11 | }, 12 | onLoad: function () { 13 | this.setData({ 14 | canvasWidth: app.SystemInfo.windowWidth * app.SystemInfo.pixelRatio, 15 | canvasHeight: app.SystemInfo.windowHeight * app.SystemInfo.pixelRatio, 16 | canvasStyleWidth: app.SystemInfo.windowWidth + "px", 17 | canvasStyleHeight: app.SystemInfo.windowHeight + "px", 18 | }); 19 | }, 20 | onReady: function () { 21 | var self = this; 22 | var query = wx.createSelectorQuery().select('#webgl').node().exec((res) => { 23 | var canvas = res[0].node; 24 | canvas.pixelRatio = app.SystemInfo.pixelRatio; 25 | canvas.width = canvas._width; 26 | canvas.height = canvas._height; 27 | canvas.clientWidth = canvas._width; 28 | canvas.clientHeight = canvas._height; 29 | canvas.style = {}; 30 | canvas.style.width = canvas.width; 31 | canvas.style.height = canvas.height; 32 | canvas.EventListenerList={}; 33 | canvas.addEventListener = function (type, func, useCapture){ 34 | canvas.EventListenerList[type] = canvas.EventListenerList[type]||[]; 35 | canvas.EventListenerList[type].push(func) 36 | } 37 | pl = new PANOLENS.init(canvas,self); 38 | panorama = new pl.ImagePanorama(canvas,'../../textures/fisheye/pano2048-1024.jpg'); 39 | //panorama = new pl.ImageLittlePlanet(canvas, '../../textures/fisheye/pano2048-1024.jpg'); 40 | viewer = new pl.Viewer({ container: canvas, wxEnv: self, controlBar:false}); 41 | viewer.add(panorama); 42 | viewer.enableControl(pl.Controls.ORBIT); 43 | //self.initDeviceOrientation(); 44 | //viewer.enableControl(pl.Controls.DEVICEORIENTATION); 45 | }) 46 | }, 47 | initDeviceOrientation: function () { 48 | var self = this; 49 | wx.startDeviceMotionListening({ 50 | interval:"game", 51 | success(){ 52 | wx.onDeviceMotionChange(self.onDeviceOrientation) 53 | } 54 | }) 55 | }, 56 | destroyDeviceOrientation: function (callback) { 57 | wx.stopDeviceMotionListening({ 58 | success(){ 59 | viewer.container.EventListenerList["deviceorientation"]=[]; 60 | typeof callback == "function" ? callback():""; 61 | } 62 | }) 63 | }, 64 | onDeviceOrientation: function (event) { 65 | var self=this; 66 | if (pl.currentorientation == 0) { 67 | event.alpha = -event.alpha; 68 | event.beta = -event.beta; 69 | } else if (pl.currentorientation == 90) { 70 | self.destroyDeviceOrientation(function () {}); 71 | } 72 | for (var i in viewer.container.EventListenerList["deviceorientation"]) { 73 | viewer.container.EventListenerList["deviceorientation"][i](event); 74 | } 75 | }, 76 | onTouchStart: function (event) { 77 | for (var i in viewer.container.EventListenerList["touchstart"]){ 78 | viewer.container.EventListenerList["touchstart"][i](event); 79 | } 80 | console.log(viewer.container); 81 | console.log(viewer.getScene()); 82 | }, 83 | onTouchMove: function (event) { 84 | for (var i in viewer.container.EventListenerList["touchmove"]) { 85 | viewer.container.EventListenerList["touchmove"][i](event); 86 | } 87 | }, 88 | onTouchEnd: function (event) { 89 | var self = this; 90 | for (var i in viewer.container.EventListenerList["touchend"]) { 91 | viewer.container.EventListenerList["touchend"][i](event); 92 | } 93 | wx.nextTick(() => { 94 | var tmpcam = viewer.getCamera(); 95 | var rescam = { position: {}, rotation: {}, fov: tmpcam.fov}; 96 | for (var i in tmpcam.position){ 97 | rescam.position[i] = parseFloat(tmpcam.position[i]).toFixed(2); 98 | } 99 | for (var i in tmpcam.rotation) { 100 | rescam.rotation[i] = parseFloat(tmpcam.rotation[i]).toFixed(2); 101 | } 102 | self.setData({ camera: rescam }); 103 | }); 104 | }, 105 | onResize(event) { 106 | var self=this; 107 | for (var i in viewer.container.EventListenerList["resize"]) { 108 | viewer.container.EventListenerList["resize"][i](event); 109 | } 110 | switch (event.deviceOrientation) { 111 | case "landscape": 112 | viewer.enableControl(pl.Controls.ORBIT); 113 | viewer.enableEffect(pl.Modes.CARDBOARD); 114 | pl.currentorientation = 90; 115 | self.destroyDeviceOrientation(); 116 | break; 117 | case "portrait": 118 | viewer.enableControl(pl.Controls.DEVICEORIENTATION); 119 | viewer.disableEffect(); 120 | pl.currentorientation = 0; 121 | self.initDeviceOrientation(); 122 | break; 123 | } 124 | for (var i in viewer.container.EventListenerList["orientationchange"]) { 125 | viewer.container.EventListenerList["orientationchange"][i](pl.currentorientation); 126 | } 127 | this.setData({ 128 | canvasWidth: viewer.container._width * app.SystemInfo.pixelRatio, 129 | canvasHeight: viewer.container._height * app.SystemInfo.pixelRatio, 130 | canvasStyleWidth: viewer.container._width + "px", 131 | canvasStyleHeight: viewer.container._height + "px", 132 | currentorientation:pl.currentorientation 133 | }); 134 | } 135 | }) 136 | --------------------------------------------------------------------------------