├── 素材火帮助.txt ├── .idea ├── .name ├── vcs.xml ├── Ge1doot.js超酷3D立体照片墙.iml ├── modules.xml └── misc.xml ├── imgs └── o.png ├── js ├── ge1doot.js └── imageTransform3D.js └── index.html /素材火帮助.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | Ge1doot.js超酷3D立体照片墙 -------------------------------------------------------------------------------- /imgs/o.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overmind1980/3d_pic_Using_Ge1doot.js/master/imgs/o.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/Ge1doot.js超酷3D立体照片墙.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /js/ge1doot.js: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // ============= micro HTML5 library ===================== 3 | // @author Gerard Ferrandez / http://www.dhteumeuleu.com/ 4 | // last update: May 27, 2013 5 | // Released under the MIT license 6 | // http://www.dhteumeuleu.com/LICENSE.html 7 | //////////////////////////////////////////////////////////// 8 | 9 | // ===== ge1doot global ===== 10 | 11 | var ge1doot = ge1doot || { 12 | json: null, 13 | screen: null, 14 | pointer: null, 15 | camera: null, 16 | loadJS: function (url, callback, data) { 17 | if (typeof url == "string") url = [url]; 18 | var load = function (src) { 19 | var script = document.createElement("script"); 20 | if (callback) { 21 | if (script.readyState){ 22 | script.onreadystatechange = function () { 23 | if (script.readyState == "loaded" || script.readyState == "complete"){ 24 | script.onreadystatechange = null; 25 | if (--n === 0) callback(data || false); 26 | } 27 | } 28 | } else { 29 | script.onload = function() { 30 | if (--n === 0) callback(data || false); 31 | } 32 | } 33 | } 34 | script.src = src; 35 | document.getElementsByTagName("head")[0].appendChild(script); 36 | } 37 | for (var i = 0, n = url.length; i < n; i++) load(url[i]); 38 | } 39 | } 40 | 41 | // ===== html/canvas container ===== 42 | 43 | ge1doot.Screen = function (setup) { 44 | ge1doot.screen = this; 45 | this.elem = document.getElementById(setup.container) || setup.container; 46 | this.ctx = this.elem.tagName == "CANVAS" ? this.elem.getContext("2d") : false; 47 | this.style = this.elem.style; 48 | this.left = 0; 49 | this.top = 0; 50 | this.width = 0; 51 | this.height = 0; 52 | this.cursor = "default"; 53 | this.setup = setup; 54 | this.resize = function () { 55 | var o = this.elem; 56 | this.width = o.offsetWidth; 57 | this.height = o.offsetHeight; 58 | for (this.left = 0, this.top = 0; o != null; o = o.offsetParent) { 59 | this.left += o.offsetLeft; 60 | this.top += o.offsetTop; 61 | } 62 | if (this.ctx) { 63 | this.elem.width = this.width; 64 | this.elem.height = this.height; 65 | } 66 | this.setup.resize && this.setup.resize(); 67 | } 68 | this.setCursor = function (type) { 69 | if (type !== this.cursor && 'ontouchstart' in window === false) { 70 | this.cursor = type; 71 | this.style.cursor = type; 72 | } 73 | } 74 | window.addEventListener('resize', function () { 75 | ge1doot.screen.resize(); 76 | }, false); 77 | !this.setup.resize && this.resize(); 78 | } 79 | 80 | // ==== unified touch events handler ==== 81 | 82 | ge1doot.Pointer = function (setup) { 83 | ge1doot.pointer = this; 84 | var self = this; 85 | var body = document.body; 86 | var html = document.documentElement; 87 | this.setup = setup; 88 | this.screen = ge1doot.screen; 89 | this.elem = this.screen.elem; 90 | this.X = 0; 91 | this.Y = 0; 92 | this.Xi = 0; 93 | this.Yi = 0; 94 | this.bXi = 0; 95 | this.bYi = 0; 96 | this.Xr = 0; 97 | this.Yr = 0; 98 | this.startX = 0; 99 | this.startY = 0; 100 | this.scale = 0; 101 | this.wheelDelta = 0; 102 | this.isDraging = false; 103 | this.hasMoved = false; 104 | this.isDown = false; 105 | this.evt = false; 106 | var sX = 0; 107 | var sY = 0; 108 | // prevent default behavior 109 | if (setup.tap) this.elem.onclick = function () { return false; } 110 | if (!setup.documentMove) { 111 | document.ontouchmove = function(e) { e.preventDefault(); } 112 | } 113 | document.addEventListener("MSHoldVisual", function(e) { e.preventDefault(); }, false); 114 | if (typeof this.elem.style.msTouchAction != 'undefined') this.elem.style.msTouchAction = "none"; 115 | 116 | this.pointerDown = function (e) { 117 | if (!this.isDown) { 118 | if (this.elem.setCapture) this.elem.setCapture(); 119 | this.isDraging = false; 120 | this.hasMoved = false; 121 | this.isDown = true; 122 | this.evt = e; 123 | this.Xr = (e.clientX !== undefined ? e.clientX : e.touches[0].clientX); 124 | this.Yr = (e.clientY !== undefined ? e.clientY : e.touches[0].clientY); 125 | this.X = sX = this.Xr - this.screen.left; 126 | this.Y = sY = this.Yr - this.screen.top + ((html && html.scrollTop) || body.scrollTop); 127 | this.setup.down && this.setup.down(e); 128 | } 129 | } 130 | this.pointerMove = function(e) { 131 | this.Xr = (e.clientX !== undefined ? e.clientX : e.touches[0].clientX); 132 | this.Yr = (e.clientY !== undefined ? e.clientY : e.touches[0].clientY); 133 | this.X = this.Xr - this.screen.left; 134 | this.Y = this.Yr - this.screen.top + ((html && html.scrollTop) || body.scrollTop); 135 | if (this.isDown) { 136 | this.Xi = this.bXi + (this.X - sX); 137 | this.Yi = this.bYi - (this.Y - sY); 138 | } 139 | if (Math.abs(this.X - sX) > 11 || Math.abs(this.Y - sY) > 11) { 140 | this.hasMoved = true; 141 | if (this.isDown) { 142 | if (!this.isDraging) { 143 | this.startX = sX; 144 | this.startY = sY; 145 | this.setup.startDrag && this.setup.startDrag(e); 146 | this.isDraging = true; 147 | } else { 148 | this.setup.drag && this.setup.drag(e); 149 | } 150 | } else { 151 | sX = this.X; 152 | sY = this.Y; 153 | } 154 | } 155 | this.setup.move && this.setup.move(e); 156 | } 157 | this.pointerUp = function(e) { 158 | this.bXi = this.Xi; 159 | this.bYi = this.Yi; 160 | if (!this.hasMoved) { 161 | this.X = sX; 162 | this.Y = sY; 163 | this.setup.tap && this.setup.tap(this.evt); 164 | } else { 165 | this.setup.up && this.setup.up(this.evt); 166 | } 167 | this.isDraging = false; 168 | this.isDown = false; 169 | this.hasMoved = false; 170 | this.setup.up && this.setup.up(this.evt); 171 | if (this.elem.releaseCapture) this.elem.releaseCapture(); 172 | this.evt = false; 173 | } 174 | this.pointerCancel = function(e) { 175 | if (this.elem.releaseCapture) this.elem.releaseCapture(); 176 | this.isDraging = false; 177 | this.hasMoved = false; 178 | this.isDown = false; 179 | this.bXi = this.Xi; 180 | this.bYi = this.Yi; 181 | sX = 0; 182 | sY = 0; 183 | } 184 | if ('ontouchstart' in window) { 185 | this.elem.ontouchstart = function (e) { self.pointerDown(e); return false; } 186 | this.elem.ontouchmove = function (e) { self.pointerMove(e); return false; } 187 | this.elem.ontouchend = function (e) { self.pointerUp(e); return false; } 188 | this.elem.ontouchcancel = function (e) { self.pointerCancel(e); return false;} 189 | } 190 | document.addEventListener("mousedown", function (e) { 191 | if ( 192 | e.target === self.elem || 193 | (e.target.parentNode && e.target.parentNode === self.elem) || 194 | (e.target.parentNode.parentNode && e.target.parentNode.parentNode === self.elem) 195 | ) { 196 | if (typeof e.stopPropagation != "undefined") { 197 | e.stopPropagation(); 198 | } else { 199 | e.cancelBubble = true; 200 | } 201 | e.preventDefault(); 202 | self.pointerDown(e); 203 | } 204 | }, false); 205 | document.addEventListener("mousemove", function (e) { self.pointerMove(e); }, false); 206 | document.addEventListener("mouseup", function (e) { 207 | self.pointerUp(e); 208 | }, false); 209 | document.addEventListener('gesturechange', function(e) { 210 | e.preventDefault(); 211 | if (e.scale > 1) self.scale = 0.1; else if (e.scale < 1) self.scale = -0.1; else self.scale = 0; 212 | self.setup.scale && self.setup.scale(e); 213 | return false; 214 | }, false); 215 | if (window.navigator.msPointerEnabled) { 216 | var nContact = 0; 217 | var myGesture = new MSGesture(); 218 | myGesture.target = this.elem; 219 | this.elem.addEventListener("MSPointerDown", function(e) { 220 | if (e.pointerType == e.MSPOINTER_TYPE_TOUCH) { 221 | myGesture.addPointer(e.pointerId); 222 | nContact++; 223 | } 224 | }, false); 225 | this.elem.addEventListener("MSPointerOut", function(e) { 226 | if (e.pointerType == e.MSPOINTER_TYPE_TOUCH) { 227 | nContact--; 228 | } 229 | }, false); 230 | this.elem.addEventListener("MSGestureHold", function(e) { 231 | e.preventDefault(); 232 | }, false); 233 | this.elem.addEventListener("MSGestureChange", function(e) { 234 | if (nContact > 1) { 235 | if (e.preventDefault) e.preventDefault(); 236 | self.scale = e.velocityExpansion; 237 | self.setup.scale && self.setup.scale(e); 238 | } 239 | return false; 240 | }, false); 241 | } 242 | if (window.addEventListener) this.elem.addEventListener('DOMMouseScroll', function(e) { 243 | if (e.preventDefault) e.preventDefault(); 244 | self.wheelDelta = e.detail * 10; 245 | self.setup.wheel && self.setup.wheel(e); 246 | return false; 247 | }, false); 248 | this.elem.onmousewheel = function () { 249 | self.wheelDelta = -event.wheelDelta * .25; 250 | self.setup.wheel && self.setup.wheel(event); 251 | return false; 252 | } 253 | } 254 | // ===== request animation frame ===== 255 | 256 | window.requestAnimFrame = (function(){ 257 | return window.requestAnimationFrame || 258 | window.webkitRequestAnimationFrame || 259 | window.mozRequestAnimationFrame || 260 | window.oRequestAnimationFrame || 261 | window.msRequestAnimationFrame || 262 | function( run ){ 263 | window.setTimeout(run, 16); 264 | }; 265 | })(); 266 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ge1doot.js三维立体相册切换 6 | 7 | 28 | 29 | 30 | 371 | 372 | 373 | 374 | 375 | 你的浏览器不支持HTML5画布技术,请使用谷歌浏览器。 376 | 377 | 378 | 379 | 380 | -------------------------------------------------------------------------------- /js/imageTransform3D.js: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // ==== HTML5 CANVAS transform Image ==== 3 | // full 3D version 4 | // @author Gerard Ferrandez / http://www.dhteumeuleu.com/ 5 | // last update: Dec 8, 2012 6 | // Released under the MIT license 7 | // http://www.dhteumeuleu.com/LICENSE.html 8 | //////////////////////////////////////////////////////////// 9 | 10 | "use strict"; 11 | 12 | var ge1doot = ge1doot || {}; 13 | ge1doot.transform3D = {}; 14 | 15 | /* ==== draw Poly ==== */ 16 | ge1doot.transform3D.drawPoly = function () { 17 | this.ctx.beginPath(); 18 | this.ctx.moveTo(this.points[0].X, this.points[0].Y); 19 | this.ctx.lineTo(this.points[1].X, this.points[1].Y); 20 | this.ctx.lineTo(this.points[2].X, this.points[2].Y); 21 | this.ctx.lineTo(this.points[3].X, this.points[3].Y); 22 | this.ctx.closePath(); 23 | } 24 | /* =============== camera constructor ================= */ 25 | ge1doot.transform3D.Camera = function (setup, func) { 26 | ge1doot.camera = this; 27 | this.x = 0; 28 | this.y = 0; 29 | this.z = 0; 30 | this.rx = 0; 31 | this.ry = 0; 32 | this.rz = 0; 33 | this.focalLength = setup.focalLength || 500; 34 | this.easeTranslation = setup.easeTranslation || 0.1; 35 | this.easeRotation = setup.easeRotation || 0.025; 36 | this.enableRx = setup.disableRx ? false : true; 37 | this.enableRy = setup.disableRy ? false : true; 38 | this.enableRz = setup.disableRz ? false : true; 39 | this.cmov = false; 40 | this.cosX = 1; 41 | this.sinX = 0; 42 | this.cosY = 1; 43 | this.sinY = 0; 44 | this.cosZ = 1; 45 | this.sinZ = 0; 46 | this.target = { 47 | over: false, 48 | elem: false, 49 | x: 0, 50 | y: 0, 51 | z: 0, 52 | rx: 0, 53 | ry: 0, 54 | rz: 0 55 | }; 56 | // ---- def custom move ---- 57 | if (func && func.move) this.cmov = func.move; 58 | } 59 | /* ==== easing ==== */ 60 | ge1doot.transform3D.Camera.prototype.ease = function (target, value) { 61 | while (Math.abs(target - value) > Math.PI) { 62 | if (target < value) value -= 2 * Math.PI; 63 | else value += 2 * Math.PI; 64 | } 65 | return (target - value) * this.easeRotation; 66 | } 67 | /* ==== move / rotate camera ==== */ 68 | ge1doot.transform3D.Camera.prototype.move = function () { 69 | // ---- run custom function ---- 70 | this.cmov && this.cmov(); 71 | // ---- translations ---- 72 | this.x += (this.target.x - this.x) * this.easeTranslation; 73 | this.y += (this.target.y - this.y) * this.easeTranslation; 74 | this.z += (this.target.z - this.z) * this.easeTranslation; 75 | // ---- rotation rx ---- 76 | if (this.enableRx) { 77 | this.rx += this.ease(this.target.rx, this.rx); 78 | this.cosX = Math.cos(this.rx); 79 | this.sinX = Math.sin(this.rx); 80 | } 81 | // ---- rotation ry ---- 82 | if (this.enableRy) { 83 | this.ry += this.ease(this.target.ry, this.ry); 84 | this.cosY = Math.cos(this.ry); 85 | this.sinY = Math.sin(this.ry); 86 | } 87 | // ---- rotation rz ---- 88 | if (this.enableRz) { 89 | this.rz += this.ease(this.target.rz, this.rz); 90 | this.cosZ = Math.cos(this.rz); 91 | this.sinZ = Math.sin(this.rz); 92 | } 93 | } 94 | /* =============== point constructor ================= */ 95 | ge1doot.transform3D.Point = function (x, y, z, tx, ty) { 96 | this.x = x; 97 | this.y = y; 98 | this.z = z; 99 | this.tx = tx || 0; 100 | this.ty = ty || 0; 101 | this.visible = false; 102 | this.scale = 0; 103 | this.X = 0; 104 | this.Y = 0; 105 | this.Z = 0; 106 | this.next = true; 107 | } 108 | /* ==== perspective projection ==== */ 109 | ge1doot.transform3D.Point.prototype.projection = function () { 110 | var sw = this.scr.width >> 1; 111 | var sh = this.scr.height >> 1; 112 | // ---- 3D coordinates ---- 113 | var nx = this.x - this.camera.x; 114 | var ny = this.y - this.camera.y; 115 | var nz = this.z - this.camera.z; 116 | // ---- 3D rotation and projection ---- 117 | if (this.camera.enableRz) { 118 | var u = this.camera.sinZ * ny + this.camera.cosZ * nx; 119 | var t = this.camera.cosZ * ny - this.camera.sinZ * nx; 120 | } else { 121 | var u = nx; 122 | var t = ny; 123 | } 124 | var s = this.camera.cosY * nz + this.camera.sinY * u; 125 | this.Z = this.camera.cosX * s - this.camera.sinX * t; 126 | this.scale = this.camera.focalLength / Math.max(1, this.Z); 127 | this.X = sw + (this.camera.cosY * u - this.camera.sinY * nz) * this.scale; 128 | this.Y = -(this.camera.y >> 1) + sh - (this.camera.sinX * s + this.camera.cosX * t) * this.scale; 129 | // ---- visibility test ---- 130 | this.visible = ( 131 | this.X > -sw * 0.5 && this.X < sw * 2.5 132 | ) && ( 133 | this.Y > -sh * 0.5 && this.Y < sh * 2.5 134 | ); 135 | // ----return next (fast loop) ---- 136 | return this.next; 137 | } 138 | /* ==== triangle constructor ==== */ 139 | ge1doot.transform3D.Triangle = function (parent, p0, p1, p2) { 140 | this.ctx = parent.ctx; 141 | this.texture = parent.texture; 142 | this.p0 = p0; 143 | this.p1 = p1; 144 | this.p2 = p2; 145 | this.d = p0.tx * (p2.ty - p1.ty) - p1.tx * p2.ty + p2.tx * p1.ty + (p1.tx - p2.tx) * p0.ty; 146 | this.pmy = p1.ty - p2.ty; 147 | this.pmx = p1.tx - p2.tx; 148 | this.pxy = p2.tx * p1.ty - p1.tx * p2.ty; 149 | if (parent.t) parent.t.next = true; 150 | } 151 | /* ==== draw triangle ==== */ 152 | ge1doot.transform3D.Triangle.prototype.draw = function () { 153 | if (this.p0.visible || this.p1.visible || this.p2.visible) { 154 | var dx, dy, d; 155 | // ---- centroid ---- 156 | var xc = (this.p0.X + this.p1.X + this.p2.X) / 3; 157 | var yc = (this.p0.Y + this.p1.Y + this.p2.Y) / 3; 158 | // ---- clipping ---- 159 | this.ctx.save(); 160 | this.ctx.beginPath(); 161 | dx = xc - this.p0.X; 162 | dy = yc - this.p0.Y; 163 | d = Math.max(Math.abs(dx), Math.abs(dy)); 164 | this.ctx.moveTo(this.p0.X - 2 * (dx / d), this.p0.Y - 2 * (dy / d)); 165 | dx = xc - this.p1.X; 166 | dy = yc - this.p1.Y; 167 | d = Math.max(Math.abs(dx), Math.abs(dy)); 168 | this.ctx.lineTo(this.p1.X - 2 * (dx / d), this.p1.Y - 2 * (dy / d)); 169 | dx = xc - this.p2.X; 170 | dy = yc - this.p2.Y; 171 | d = Math.max(Math.abs(dx), Math.abs(dy)); 172 | this.ctx.lineTo(this.p2.X - 2 * (dx / d), this.p2.Y - 2 * (dy / d)); 173 | this.ctx.closePath(); 174 | this.ctx.clip(); 175 | // ---- transform ---- 176 | var t0 = this.p2.X - this.p1.X, 177 | t1 = this.p1.Y - this.p2.Y, 178 | t2 = this.p2.ty * this.p1.X, 179 | t3 = this.p1.tx * this.p2.X, 180 | t4 = this.p2.ty * this.p1.Y, 181 | t5 = this.p1.ty * this.p2.X, 182 | t6 = this.p1.ty * this.p2.Y, 183 | t7 = this.p2.tx * this.p1.X, 184 | t8 = this.p1.tx * this.p2.Y, 185 | t9 = this.p2.tx * this.p1.Y; 186 | this.ctx.transform( 187 | -(this.p0.ty * t0 - t5 + t2 + this.pmy * this.p0.X) / this.d, // m11 188 | (t6 + this.p0.ty * t1 - t4 - this.pmy * this.p0.Y) / this.d, // m12 189 | (this.p0.tx * t0 - t3 + t7 + this.pmx * this.p0.X) / this.d, // m21 190 | -(t8 + this.p0.tx * t1 - t9 - this.pmx * this.p0.Y) / this.d, // m22 191 | (this.p0.tx * (t2 - t5) + this.p0.ty * (t3 - t7) + this.pxy * this.p0.X) / this.d, // dx 192 | (this.p0.tx * (t4 - t6) + this.p0.ty * (t8 - t9) + this.pxy * this.p0.Y) / this.d // dy 193 | ); 194 | // ---- draw ---- 195 | this.ctx.drawImage(this.texture, 0, 0); 196 | this.ctx.restore(); 197 | } 198 | return this.next; 199 | } 200 | /* ===================== image constructor ========================== */ 201 | ge1doot.transform3D.Image = function (parent, imgSrc, lev, callback) { 202 | this.parent = parent; 203 | this.points = []; 204 | this.triangles = []; 205 | this.ctx = ge1doot.screen.ctx; 206 | this.pointer = ge1doot.pointer; 207 | this.texture = new Image(); 208 | this.texture.src = imgSrc; 209 | this.isLoading = true; 210 | this.callback = callback; 211 | this.textureWidth = 0; 212 | this.textureHeight = 0; 213 | this.level = lev || 1; 214 | this.visible = false; 215 | this.t = false; 216 | if (!ge1doot.transform3D.Point.prototype.scr) { 217 | ge1doot.transform3D.Point.prototype.scr = ge1doot.screen; 218 | ge1doot.transform3D.Point.prototype.camera = ge1doot.camera; 219 | } 220 | } 221 | /* ==== drawPoly prototype ==== */ 222 | ge1doot.transform3D.Image.prototype.drawPoly = ge1doot.transform3D.drawPoly; 223 | /* ==== change tessellation level prototype ==== */ 224 | ge1doot.transform3D.Image.prototype.setLevel = function (level) { 225 | this.points.length = 0; 226 | this.triangles.length = 0; 227 | this.level = level; 228 | this.loading(); 229 | } 230 | /* ==== loading prototype ==== */ 231 | ge1doot.transform3D.Image.prototype.loading = function () { 232 | if (this.texture.complete) { 233 | var dir = [0,1,1,0,0,0,1,1]; 234 | this.isLoading = false; 235 | // ---- image size ---- 236 | this.textureWidth = this.texture.width; 237 | this.textureHeight = this.texture.height; 238 | // ---- isLoaded callback --- 239 | this.callback && this.callback.isLoaded && this.callback.isLoaded(this); 240 | // ---- texture position ---- 241 | for (var i = -1, p; p = this.points[++i];) { 242 | p.tx = this.textureWidth * dir[i]; 243 | p.ty = this.textureHeight * dir[i+4]; 244 | } 245 | // ---- triangularization ---- 246 | this.triangulate(this.points[0], this.points[1], this.points[2], this.level); 247 | this.triangulate(this.points[0], this.points[2], this.points[3], this.level); 248 | // ---- last point ---- 249 | this.points[this.points.length - 1].next = false; 250 | } 251 | } 252 | /* ==== vector bisection function ==== */ 253 | ge1doot.transform3D.Image.prototype.subdivise = function (p0, p1) { 254 | return { 255 | x: (p1.x + p0.x) * 0.5, 256 | y: (p1.y + p0.y) * 0.5, 257 | z: (p1.z + p0.z) * 0.5, 258 | tx: (p1.tx + p0.tx) * 0.5, 259 | ty: (p1.ty + p0.ty) * 0.5 260 | }; 261 | } 262 | /* ==== triangulation ==== */ 263 | ge1doot.transform3D.Image.prototype.triangulate = function (p0, p1, p2, level) { 264 | level--; 265 | if (level === 0) { 266 | // final triangle 267 | this.t = new ge1doot.transform3D.Triangle(this, p0, p1, p2); 268 | this.triangles.push(this.t); 269 | } else { 270 | // ---- subdivision ---- 271 | var p01 = this.subdivise(p0, p1); 272 | var p12 = this.subdivise(p1, p2); 273 | var p20 = this.subdivise(p2, p0); 274 | // ---- insert new points ---- 275 | this.points.push(p01 = new ge1doot.transform3D.Point(p01.x, p01.y, p01.z, p01.tx, p01.ty)); 276 | this.points.push(p12 = new ge1doot.transform3D.Point(p12.x, p12.y, p12.z, p12.tx, p12.ty)); 277 | this.points.push(p20 = new ge1doot.transform3D.Point(p20.x, p20.y, p20.z, p20.tx, p20.ty)); 278 | // ---- recursive triangulation ---- 279 | this.triangulate(p0, p01, p20, level); 280 | this.triangulate(p01, p1, p12, level); 281 | this.triangulate(p20, p12, p2, level); 282 | this.triangulate(p01, p12, p20, level); 283 | } 284 | } 285 | /* ==== transform prototype ==== */ 286 | ge1doot.transform3D.Image.prototype.transform3D = function (backfaceTest) { 287 | if (this.isLoading) { 288 | // ---- image is loading ---- 289 | this.loading(); 290 | return false; 291 | } else { 292 | // ---- project points ---- 293 | for ( 294 | var i = 0; 295 | this.points[i++].projection(); 296 | ); 297 | if (backfaceTest) { 298 | var p0 = this.points[0]; 299 | var p1 = this.points[1]; 300 | var p2 = this.points[2]; 301 | return ( 302 | ((p1.Y - p0.Y) / (p1.X - p0.X) - 303 | (p2.Y - p0.Y) / (p2.X - p0.X) < 0) ^ 304 | (p0.X <= p1.X == p0.X > p2.X) 305 | ); 306 | } else return true; 307 | } 308 | } 309 | /* ==== draw prototype ==== */ 310 | ge1doot.transform3D.Image.prototype.draw = function () { 311 | if (!this.isLoading) { 312 | // ---- draw triangles ---- 313 | for ( 314 | var i = 0; 315 | this.triangles[i++].draw(); 316 | ); 317 | } 318 | } 319 | /* ==== isPointerInside prototype ==== */ 320 | ge1doot.transform3D.Image.prototype.isPointerInside = function (x, y) { 321 | this.drawPoly(this.points); 322 | return this.ctx.isPointInPath(x, y); 323 | } --------------------------------------------------------------------------------