/src/com/wagerfield/display/DistortedBitmap.as

https://github.com/wagerfield/girder · ActionScript · 272 lines · 170 code · 50 blank · 52 comment · 11 complexity · e39165acd2fe97af94a0bb2813b6ed92 MD5 · raw file

  1. /**
  2. * Copyright (C) 2011 by Matthew Wagerfield
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. * THE SOFTWARE.
  21. */
  22. package com.wagerfield.display
  23. {
  24. import flash.display.BitmapData;
  25. import flash.display.Sprite;
  26. import flash.geom.Matrix;
  27. import flash.geom.Point;
  28. public class DistortedBitmap extends Sprite
  29. {
  30. private const MIN_SEGS:uint = 1;
  31. private var _bmd:BitmapData;
  32. private var _w:Number;
  33. private var _h:Number;
  34. private var _hSegs:Number;
  35. private var _vSegs:Number;
  36. private var _pointArr:Array;
  37. private var _triArr:Array;
  38. private var _smoothing:Boolean;
  39. private var _drawLines:Boolean;
  40. public function DistortedBitmap(bmd:BitmapData = null, hSeg:Number = 4, vSeg:Number = 4)
  41. {
  42. _bmd = bmd;
  43. _hSegs = hSeg;
  44. _vSegs = vSeg;
  45. _smoothing = true;
  46. _drawLines = false;
  47. config();
  48. }
  49. private function config():void
  50. {
  51. if (_bmd != null)
  52. {
  53. var p0:Object;
  54. var p1:Object;
  55. var p2:Object;
  56. var ix:uint;
  57. var iy:uint;
  58. _pointArr = new Array();
  59. _triArr = new Array();
  60. _hSegs = _hSegs < MIN_SEGS ? MIN_SEGS : _hSegs;
  61. _vSegs = _hSegs < MIN_SEGS ? MIN_SEGS : _hSegs;
  62. _w = _bmd.width ;
  63. _h = _bmd.height;
  64. // CREATE SEGMENT DIVISION POINTS
  65. for (ix = 0; ix <= _hSegs; ix++)
  66. {
  67. // _pointArr[ix] = new Array();
  68. for (iy = 0; iy <= _vSegs; iy++)
  69. {
  70. var x:Number = ix * (_w / _hSegs);
  71. var y:Number = iy * (_h / _vSegs);
  72. // _pointArr[ix][iy] = {x:x, y:y, sx:x, sy:y};
  73. _pointArr.push({x:x, y:y, sx:x, sy:y});
  74. }
  75. }
  76. // CREATE TRIANGLES
  77. for (ix = 0; ix < _hSegs; ix++)
  78. {
  79. for (iy = 0; iy < _vSegs; iy++)
  80. {
  81. // CREATE TOP LEFT TRIANGLE
  82. // p0 = _pointArr[ iy ][ ix ]; // TOP LEFT POINT
  83. // p1 = _pointArr[iy + 1][ix]; // BOTTOM LEFT POINT
  84. // p2 = _pointArr[iy][ix + 1]; // TOP RIGHT POINT
  85. p0 = _pointArr[iy + ix * (_hSegs + 1)];
  86. // TOP LEFT POINT
  87. p1 = _pointArr[iy + ix * (_hSegs + 1) + 1];
  88. // BOTTOM LEFT POINT
  89. p2 = _pointArr[iy + (ix + 1) * (_hSegs + 1)];
  90. // TOP RIGHT POINT
  91. addTriangle(p0, p1, p2);
  92. // CREATE BOTTOM RIGHT TRIANGLE
  93. // p0 = _pointArr[iy+1][ix+1]; // BOTTOM RIGHT POINT
  94. // p1 = _pointArr[iy][ix + 1]; // TOP RIGHT POINT
  95. // p2 = _pointArr[iy + 1][ix]; // BOTTOM LEFT POINT
  96. p0 = _pointArr[iy + (ix + 1) * (_vSegs + 1) + 1];
  97. // BOTTOM RIGHT POINT
  98. p1 = _pointArr[iy + (ix + 1) * (_vSegs + 1)];
  99. // TOP RIGHT POINT
  100. p2 = _pointArr[iy + ix * (_vSegs + 1) + 1];
  101. // BOTTOM LEFT POINT
  102. addTriangle(p0, p1, p2);
  103. }
  104. }
  105. render();
  106. }
  107. }
  108. private function addTriangle(p0:Object, p1:Object, p2:Object):void
  109. {
  110. var mat:Matrix = new Matrix();
  111. mat.b = _h / (p2.x - p0.x);
  112. mat.c = _w / (p1.y - p0.y);
  113. mat.ty = -p0.x * mat.b;
  114. mat.tx = -p0.y * mat.c;
  115. _triArr.push([p0, p1, p2, mat]);
  116. }
  117. private function render():void
  118. {
  119. var p0:Object;
  120. var p1:Object;
  121. var p2:Object;
  122. var ih:Number = 1 / _h;
  123. var iw:Number = 1 / _w;
  124. var sM:Matrix = new Matrix();
  125. var tM:Matrix = new Matrix();
  126. var l:Number = _triArr.length;
  127. this.graphics.clear();
  128. while (--l > -1)
  129. {
  130. p0 = _triArr[l][0];
  131. p1 = _triArr[l][1];
  132. p2 = _triArr[l][2];
  133. tM = _triArr[l][3];
  134. sM.a = (p1.sx - p0.sx) * iw;
  135. sM.b = (p1.sy - p0.sy) * iw;
  136. sM.c = (p2.sx - p0.sx) * ih;
  137. sM.d = (p2.sy - p0.sy) * ih;
  138. sM.tx = p0.sx;
  139. sM.ty = p0.sy;
  140. sM = concat(sM, tM);
  141. if (_drawLines) graphics.lineStyle(1, 0xFFFFFF, 0.75);
  142. graphics.beginBitmapFill(_bmd, sM, false, _smoothing);
  143. graphics.moveTo(p0.sx, p0.sy);
  144. graphics.lineTo(p1.sx, p1.sy);
  145. graphics.lineTo(p2.sx, p2.sy);
  146. graphics.endFill();
  147. }
  148. }
  149. private function concat(m1:Matrix, m2:Matrix):Matrix
  150. {
  151. var mat:Matrix = new Matrix();
  152. mat.a = m1.c * m2.b;
  153. mat.b = m1.d * m2.b;
  154. mat.c = m1.a * m2.c;
  155. mat.d = m1.b * m2.c;
  156. mat.tx = m1.a * m2.tx + m1.c * m2.ty + m1.tx;
  157. mat.ty = m1.b * m2.tx + m1.d * m2.ty + m1.ty;
  158. return mat;
  159. }
  160. public function distort(tl:Point, tr:Point, bl:Point, br:Point):void
  161. {
  162. if (_bmd != null)
  163. {
  164. var l:Number = _pointArr.length;
  165. while (--l > -1)
  166. {
  167. var gx:Number = _pointArr[l].x / _w;
  168. var gy:Number = _pointArr[l].y / _h;
  169. var bx:Number = tl.x + gy * (bl.x - tl.x);
  170. var by:Number = tl.y + gy * (bl.y - tl.y);
  171. _pointArr[l].sx = bx + gx * ((tr.x + gy * (br.x - tr.x)) - bx);
  172. _pointArr[l].sy = by + gx * ((tr.y + gy * (br.y - tr.y)) - by);
  173. }
  174. /*
  175. for(var ix:uint = 0; ix < _pointArr.length; ix++)
  176. for(var iy:uint = 0; iy < _pointArr[ix].length; iy++)
  177. {
  178. var gx = _pointArr[ix][iy].x / _w;
  179. var gy = _pointArr[ix][iy].y / _h;
  180. var bx = tl.x + gy * (bl.x - tl.x);
  181. var by = tl.y + gy * (bl.y - tl.y);
  182. _pointArr[ix][iy].sx = bx + gx * ((tr.x + gy * (br.x - tr.x)) - bx);
  183. _pointArr[ix][iy].sy = by + gx * ((tr.y + gy * (br.y - tr.y)) - by);
  184. }
  185. */
  186. render();
  187. }
  188. }
  189. public function set vSegs(segs:uint):void
  190. {
  191. _vSegs = segs;
  192. config();
  193. }
  194. public function set hSegs(segs:uint):void
  195. {
  196. _hSegs = segs;
  197. config();
  198. }
  199. public function set bitmapData(bmd:BitmapData):void
  200. {
  201. _bmd = bmd;
  202. config();
  203. }
  204. public function set drawLines(draw:Boolean):void
  205. {
  206. _drawLines = draw;
  207. }
  208. public function set smoothing(smooth:Boolean):void
  209. {
  210. _smoothing = smooth;
  211. }
  212. public function get drawLines():Boolean
  213. {
  214. return _drawLines;
  215. }
  216. public function get smoothing():Boolean
  217. {
  218. return _smoothing;
  219. }
  220. }
  221. }