/com/zehfernando/display/abstracts/PerspectiveSprite.as

https://github.com/duponce/as3 · ActionScript · 199 lines · 135 code · 44 blank · 20 comment · 1 complexity · 8963db520851b262bbd318eb224adc98 MD5 · raw file

  1. package com.zehfernando.display.abstracts {
  2. import flash.events.Event;
  3. import flash.display.DisplayObject;
  4. import flash.display.Sprite;
  5. import flash.geom.PerspectiveProjection;
  6. import flash.geom.Point;
  7. /**
  8. * @author zeh
  9. */
  10. public class PerspectiveSprite extends Sprite {
  11. // Properties
  12. private var _assumedWidth:Number;
  13. private var _assumedHeight:Number;
  14. private var _redrawScheduled:Boolean;
  15. // Instances
  16. private var _topLeft:Point;
  17. private var _topRight:Point;
  18. private var _bottomLeft:Point;
  19. private var _bottomRight:Point;
  20. private var _container3d:Sprite;
  21. // ================================================================================================================
  22. // CONSTRUCTOR ----------------------------------------------------------------------------------------------------
  23. public function PerspectiveSprite(__assumedWidth:Number = 640, __assumedHeight:Number = 480) {
  24. _assumedWidth = __assumedWidth;
  25. _assumedHeight = __assumedHeight;
  26. _container3d = new Sprite();
  27. super.addChild(_container3d);
  28. _topLeft = new Point(0, 0);
  29. _topRight = new Point(_assumedWidth, 0);
  30. _bottomLeft = new Point(0, _assumedHeight);
  31. _bottomRight = new Point(_assumedWidth, _assumedHeight);
  32. scheduleRedraw();
  33. }
  34. // ================================================================================================================
  35. // INTERNAL INTERFACE ---------------------------------------------------------------------------------------------
  36. private function redrawPerspective(): void {
  37. // 3D Transforms
  38. // Based on wh0's work:
  39. // http://wonderfl.net/c/sxQJ
  40. // With original matrix equations from Mathlab
  41. var w:Number = _assumedWidth;
  42. var h:Number = _assumedHeight;
  43. removeTransform();
  44. _container3d.rotationX = 0;
  45. var pp:PerspectiveProjection = new PerspectiveProjection();
  46. pp.projectionCenter = new Point (640, 400); // Doesn't matter?
  47. transform.perspectiveProjection = pp;
  48. var v:Vector.<Number> = _container3d.transform.matrix3D.rawData;
  49. var cx:Number = transform.perspectiveProjection.projectionCenter.x;
  50. var cy:Number = transform.perspectiveProjection.projectionCenter.y;
  51. var cz:Number = transform.perspectiveProjection.focalLength;
  52. v[12] = _topLeft.x;
  53. v[13] = _topLeft.y;
  54. v[0] = -(cx*_topLeft.x*_bottomLeft.y-cx*_bottomLeft.x*_topLeft.y-cx*_topLeft.x*_bottomRight.y-cx*_topRight.x*_bottomLeft.y+cx*_bottomLeft.x*_topRight.y+cx*_bottomRight.x*_topLeft.y+cx*_topRight.x*_bottomRight.y-cx*_bottomRight.x*_topRight.y-_topLeft.x*_bottomLeft.x*_topRight.y+_topRight.x*_bottomLeft.x*_topLeft.y+_topLeft.x*_bottomRight.x*_topRight.y-_topRight.x*_bottomRight.x*_topLeft.y+_topLeft.x*_bottomLeft.x*_bottomRight.y-_topLeft.x*_bottomRight.x*_bottomLeft.y-_topRight.x*_bottomLeft.x*_bottomRight.y+_topRight.x*_bottomRight.x*_bottomLeft.y)/(_topRight.x*_bottomLeft.y-_bottomLeft.x*_topRight.y-_topRight.x*_bottomRight.y+_bottomRight.x*_topRight.y+_bottomLeft.x*_bottomRight.y-_bottomRight.x*_bottomLeft.y) / w;
  55. v[1] = -(cy*_topLeft.x*_bottomLeft.y-cy*_bottomLeft.x*_topLeft.y-cy*_topLeft.x*_bottomRight.y-cy*_topRight.x*_bottomLeft.y+cy*_bottomLeft.x*_topRight.y+cy*_bottomRight.x*_topLeft.y+cy*_topRight.x*_bottomRight.y-cy*_bottomRight.x*_topRight.y-_topLeft.x*_topRight.y*_bottomLeft.y+_topRight.x*_topLeft.y*_bottomLeft.y+_topLeft.x*_topRight.y*_bottomRight.y-_topRight.x*_topLeft.y*_bottomRight.y+_bottomLeft.x*_topLeft.y*_bottomRight.y-_bottomRight.x*_topLeft.y*_bottomLeft.y-_bottomLeft.x*_topRight.y*_bottomRight.y+_bottomRight.x*_topRight.y*_bottomLeft.y)/(_topRight.x*_bottomLeft.y-_bottomLeft.x*_topRight.y-_topRight.x*_bottomRight.y+_bottomRight.x*_topRight.y+_bottomLeft.x*_bottomRight.y-_bottomRight.x*_bottomLeft.y) / w;
  56. v[2] = (cz*_topLeft.x*_bottomLeft.y-cz*_bottomLeft.x*_topLeft.y-cz*_topLeft.x*_bottomRight.y-cz*_topRight.x*_bottomLeft.y+cz*_bottomLeft.x*_topRight.y+cz*_bottomRight.x*_topLeft.y+cz*_topRight.x*_bottomRight.y-cz*_bottomRight.x*_topRight.y)/(_topRight.x*_bottomLeft.y-_bottomLeft.x*_topRight.y-_topRight.x*_bottomRight.y+_bottomRight.x*_topRight.y+_bottomLeft.x*_bottomRight.y-_bottomRight.x*_bottomLeft.y) / w;
  57. v[4] = (cx*_topLeft.x*_topRight.y-cx*_topRight.x*_topLeft.y-cx*_topLeft.x*_bottomRight.y+cx*_topRight.x*_bottomLeft.y-cx*_bottomLeft.x*_topRight.y+cx*_bottomRight.x*_topLeft.y+cx*_bottomLeft.x*_bottomRight.y-cx*_bottomRight.x*_bottomLeft.y-_topLeft.x*_topRight.x*_bottomLeft.y+_topRight.x*_bottomLeft.x*_topLeft.y+_topLeft.x*_topRight.x*_bottomRight.y-_topLeft.x*_bottomRight.x*_topRight.y+_topLeft.x*_bottomRight.x*_bottomLeft.y-_bottomLeft.x*_bottomRight.x*_topLeft.y-_topRight.x*_bottomLeft.x*_bottomRight.y+_bottomLeft.x*_bottomRight.x*_topRight.y)/(_topRight.x*_bottomLeft.y-_bottomLeft.x*_topRight.y-_topRight.x*_bottomRight.y+_bottomRight.x*_topRight.y+_bottomLeft.x*_bottomRight.y-_bottomRight.x*_bottomLeft.y) / h;
  58. v[5] = (cy*_topLeft.x*_topRight.y-cy*_topRight.x*_topLeft.y-cy*_topLeft.x*_bottomRight.y+cy*_topRight.x*_bottomLeft.y-cy*_bottomLeft.x*_topRight.y+cy*_bottomRight.x*_topLeft.y+cy*_bottomLeft.x*_bottomRight.y-cy*_bottomRight.x*_bottomLeft.y-_topLeft.x*_topRight.y*_bottomLeft.y+_bottomLeft.x*_topLeft.y*_topRight.y+_topRight.x*_topLeft.y*_bottomRight.y-_bottomRight.x*_topLeft.y*_topRight.y+_topLeft.x*_bottomLeft.y*_bottomRight.y-_bottomLeft.x*_topLeft.y*_bottomRight.y-_topRight.x*_bottomLeft.y*_bottomRight.y+_bottomRight.x*_topRight.y*_bottomLeft.y)/(_topRight.x*_bottomLeft.y-_bottomLeft.x*_topRight.y-_topRight.x*_bottomRight.y+_bottomRight.x*_topRight.y+_bottomLeft.x*_bottomRight.y-_bottomRight.x*_bottomLeft.y) / h;
  59. v[6] = -(cz*_topLeft.x*_topRight.y-cz*_topRight.x*_topLeft.y-cz*_topLeft.x*_bottomRight.y+cz*_topRight.x*_bottomLeft.y-cz*_bottomLeft.x*_topRight.y+cz*_bottomRight.x*_topLeft.y+cz*_bottomLeft.x*_bottomRight.y-cz*_bottomRight.x*_bottomLeft.y)/(_topRight.x*_bottomLeft.y-_bottomLeft.x*_topRight.y-_topRight.x*_bottomRight.y+_bottomRight.x*_topRight.y+_bottomLeft.x*_bottomRight.y-_bottomRight.x*_bottomLeft.y) / h;
  60. try {
  61. _container3d.transform.matrix3D.rawData = v;
  62. } catch(e:Error) {
  63. trace("PerspectiveSprite :: Error: " + e);
  64. }
  65. }
  66. private function scheduleRedraw(): void {
  67. if (!_redrawScheduled) {
  68. addEventListener(Event.EXIT_FRAME, onExitFrameRedraw);
  69. _redrawScheduled = true;
  70. }
  71. }
  72. // ================================================================================================================
  73. // EVENT INTERFACE ------------------------------------------------------------------------------------------------
  74. protected function onExitFrameRedraw(e:Event): void {
  75. _redrawScheduled = false;
  76. removeEventListener(Event.EXIT_FRAME, onExitFrameRedraw);
  77. redrawPerspective();
  78. }
  79. // ================================================================================================================
  80. // PUBLIC INTERFACE -----------------------------------------------------------------------------------------------
  81. public function removeTransform(): void {
  82. _container3d.transform.matrix3D = null;
  83. }
  84. // Public overrides
  85. override public function addChild(__child:DisplayObject): DisplayObject {
  86. return _container3d.addChild(__child);
  87. }
  88. override public function addChildAt(__child:DisplayObject, __index:int): DisplayObject {
  89. return _container3d.addChildAt(__child, __index);
  90. }
  91. override public function getChildAt(__index:int): DisplayObject {
  92. return _container3d.getChildAt(__index);
  93. }
  94. override public function getChildByName(__name:String): DisplayObject {
  95. return _container3d.getChildByName(__name);
  96. }
  97. override public function getChildIndex(__child:DisplayObject): int {
  98. return _container3d.getChildIndex(__child);
  99. }
  100. override public function removeChild(__child:DisplayObject): DisplayObject {
  101. return _container3d.removeChild(__child);
  102. }
  103. override public function removeChildAt(__index:int): DisplayObject {
  104. return _container3d.removeChildAt(__index);
  105. }
  106. override public function setChildIndex(__child:DisplayObject, __index:int): void {
  107. _container3d.setChildIndex(__child, __index);
  108. }
  109. override public function swapChildren(__child1:DisplayObject, __child2:DisplayObject): void {
  110. _container3d.swapChildren(__child1, __child2);
  111. }
  112. override public function swapChildrenAt(__index1:int, __index2:int): void {
  113. _container3d.swapChildrenAt(__index1, __index2);
  114. }
  115. override public function get numChildren() : int {
  116. return _container3d.numChildren;
  117. }
  118. // ================================================================================================================
  119. // ACCESSOR INTERFACE ---------------------------------------------------------------------------------------------
  120. public function get topLeft(): Point {
  121. return _topLeft;
  122. }
  123. public function set topLeft(__value:Point): void {
  124. _topLeft = __value;
  125. scheduleRedraw();
  126. }
  127. public function get topRight(): Point {
  128. return _topRight;
  129. }
  130. public function set topRight(__value:Point): void {
  131. _topRight = __value;
  132. scheduleRedraw();
  133. }
  134. public function get bottomLeft(): Point {
  135. return _bottomLeft;
  136. }
  137. public function set bottomLeft(__value:Point): void {
  138. _bottomLeft = __value;
  139. scheduleRedraw();
  140. }
  141. public function get bottomRight(): Point {
  142. return _bottomRight;
  143. }
  144. public function set bottomRight(__value:Point): void {
  145. _bottomRight = __value;
  146. scheduleRedraw();
  147. }
  148. public function get assumedWidth():Number {
  149. return _assumedWidth;
  150. }
  151. public function get assumedHeight():Number {
  152. return _assumedHeight;
  153. }
  154. }
  155. }