Hello, I need a way to programmatically rotate an object around an arbitrary axis.
I've been trying to implement this using the objects transform matrix, with the basic algorithm: 1) Translate axis point to origin 2) Rotate 3) Translate back to axis point This approach seems to work, except that on each rotation the object slightly off the axis. OBSERVATIONS: 1) The object always seems to drift in the -x/-y direction, even if I reverse the direction of rotation 2) On each rotation in order to translate the axis point back to the origin, I need to calculate the location of the axis point given the rotating object's current rotation. I notice that after the first rotation, the distance from the rotating object's registration point to its access is always slightly off. I've tried calculating the axis position using Matrix::deltaTransformPoint() and Point::polar() and I have the same drift problem with both. ENVIRONMENT: Flash 9/Flex 2 Anyone have any ideas what's going on here or how to fix this? Big thanks in advance for any help. --Larry CODE SAMPLE: I made this stripped down example of the problem in Flex: <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init();"> <mx:Script> <![CDATA[ private var m_object:Sprite = null; private var m_axis:Sprite = null; private var m_axisFromObjOrig:Point = null; private static var OBJECT_X:Number = 100; private static var OBJECT_Y:Number = 100; private static var OBJECT_WIDTH:Number = 100; private static var OBJECT_HEIGHT:Number = 40; private static var AXIS_X_OFF:Number = OBJECT_WIDTH/2; private static var AXIS_Y_OFF:Number = 0; public function init():void { var stage:Stage = Application.application.parent.stage; /*==================================== * DRAW THE MAIN OBJECT *===================================*/ m_object = new Sprite(); stage.addChild(m_object); m_object.x = OBJECT_X; m_object.y = OBJECT_Y; var g:Graphics = m_object.graphics; g.lineStyle(1, 0xff0000); g.beginFill(0x00ff00); g.drawEllipse(0 - (OBJECT_WIDTH/2), 0 - (OBJECT_HEIGHT/2), OBJECT_WIDTH, OBJECT_HEIGHT); g.endFill(); /*============================================= * DRAW THE CENTERPOINT INSIDE THE MAIN OBJECT *============================================*/ var centerPoint:Sprite = new Sprite(); m_object.addChild(centerPoint); centerPoint.x = 0; centerPoint.y = 0; g = centerPoint.graphics; g.lineStyle(1, 0x000000); g.beginFill(0x000000); g.drawCircle(0, 0, .5); g.endFill(); /*============================================= * DRAW THE AXIS POINT INSIDE THE MAIN OBJECT *============================================*/ var axisPoint:Sprite = new Sprite(); m_object.addChild(axisPoint); axisPoint.x = AXIS_X_OFF; axisPoint.y = AXIS_Y_OFF; g = centerPoint.graphics; g.lineStyle(1, 0x000000); g.beginFill(0x000000); g.drawCircle(AXIS_X_OFF, AXIS_Y_OFF, 1); g.endFill(); /*============================================= * DRAW THE AXIS POINT FIXED ON THE STAGE *============================================*/ m_axis = new Sprite(); stage.addChild(m_axis); m_axis.x = OBJECT_X + AXIS_X_OFF; m_axis.y = OBJECT_Y + AXIS_Y_OFF; g = m_axis.graphics; g.lineStyle(1, 0x000000); g.beginFill(0x000000); g.drawCircle(0, 0, 2); g.endFill(); m_axisFromObjOrig = new Point(OBJECT_WIDTH/2, 0); var t:Timer = new Timer(20, 1000); /*==================================================== * BELOW YOU CAN SWAP THE COMMENTS TO USE EITHER * THE rotateWithDeltaTransform * OR THE rotateWithPolar * VERSION OF THE ROTATION FUNCTION *===================================================*/ //t.addEventListener(TimerEvent.TIMER, rotateWithDeltaTransform); t.addEventListener(TimerEvent.TIMER, rotateWithPolar); t.start(); } public function rotateWithDeltaTransform(evt:Event = null, angle:Number = Math.PI/360):void { var axis:Point = m_object.transform.matrix.deltaTransformPoint(m_axisFromObjOrig); axisRotate(m_object, axis, angle); } public function rotateWithPolar(evt:Event = null, angle:Number = Math.PI/360):void { var rotRads:Number = Math.PI * m_object.rotation / 180; var axis:Point = Point.polar(OBJECT_WIDTH/2, rotRads); axisRotate(m_object, axis, angle); } private function axisRotate(obj:DisplayObject, axis:Point, angle:Number):void { validateAxisLen(axis); var temp:Matrix = obj.transform.matrix; var pivotX:Number = obj.x + axis.x; var pivotY:Number = obj.y + axis.y; temp.translate(0 - pivotX, 0 - pivotY); temp.rotate(angle); temp.translate(pivotX, pivotY); obj.transform.matrix = temp; } private function validateAxisLen(axis:Point):void { var orig:Point = new Point(0, 0); var len:Number = Point.distance(orig, axis); var correctLen:Number = Point.distance(orig, m_axisFromObjOrig); var err:Number = correctLen - len; if(err != 0) { trace("Axis location is off by " + err + ": len=" + len + ", correctLen=" + correctLen); } } ]]> </mx:Script> </mx:Application>
_______________________________________________ osflash mailing list [email protected] http://osflash.org/mailman/listinfo/osflash_osflash.org
