├── 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 |
--------------------------------------------------------------------------------