[osflash] drift problem rotating an object around an arbitrary axis
larry kirschner
larrykirschner at gmail.com
Wed Feb 14 19:54:30 EST 2007
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>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://osflash.org/pipermail/osflash_osflash.org/attachments/20070214/115ae79c/attachment-0001.htm
More information about the osflash
mailing list