Hi everyone.
Back after a computer crash and lot of time spend to rewrite what i
forgot to backup...
well...
Since I'm using away3D in order to tween a camera in front of an
object with a specified distance
i'm using this :
private function onMouseClickOnObject(event:MouseEvent3D):void {
var object:Object3D = event.object;
//doRotation = false;
//get a target Number3D on one of the axis of object here on the
normal of the plane
var translated:Number3D = setTarget(object,130,Number3D.UP);
var dir:Number3D = new Number3D;
dir.sub(translated,object.position);
var angRadianY : Number = Math.atan2(dir.x, dir.z);
var angleY : Number = angRadianY*180/Math.PI - 180;
TweenMax.to(camera,1,
{x:translated.x,y:translated.y,z:translated.z,rotationY:angleY,rotationX:-
angleX,onComplete:function():void{}});
}
private function setTarget
(object:Object3D,distance:Number,axis:Number3D=null):Number3D
{
var target:Number3D = new Number3D;
var _axis:Number3D = axis;
var _object:Object3D = object;
var _distance:Number = distance;
_axis.normalize();
var _vector:Number3D = new Number3D();
_vector.rotate(_axis,_object.transform);
target.x = _object.x+distance*_vector.x;
target.y = _object.y+distance*_vector.y;
target.z = _object.z+distance*_vector.z;
return target;
}
and it works well here on the Y axis rotation,and it used to fit my
needs. But using the same trig i can't get it right for other
rotations.
the advantage of this method was to return eulers angle to play with
in any tween engine, in a "usual" way for 2d actionscripters..
Si I decide to play with quaternion and matrix.
I implemented the Quaternion class so I can use some
Quaternion.quaternion2Matrix, Quaternion.createFromMatrix,
and Quaternion.slerp some static method used in Papervision that I
thought were missing.
now I can do that :
function onMouseClickOnObject(e:MouseEvent3D):void
{
var cameraTarget:Object3D = new Object3D;
cameraTarget.transform = e.target.transform;//e target is the
object I want to face on the 3 axis.
cameraTarget.moveUp(200);
createTween(cameraTarget);
}
function createTween(target:Object3D):void
{
plan.slerp = 0;///implemanting a simple public slerp property in
object3D class
var tweenObject:Object = {};
tweenObject.x = target.x;
tweenObject.y = target.y;
tweenObject.z = target.z;
tweenObject.bezierThrough = [{x:0, y:0, z:0, slerp:.1}];
tweenObject.ease = "Cubic.easeInOut";
tweenObject.slerp = 1;//slerp
tweenObject.onUpdate = camera_updateCallback;
startQuaternion = Quaternion.createFromMatrix(plan.transform);
endQuaternion = Quaternion.createFromMatrix(target.transform);
endQuaternion.x = endQuaternion.x;
endQuaternion.y = endQuaternion.y;
endQuaternion.z = endQuaternion.z;
endQuaternion.w = endQuaternion.w;
trace(startQuaternion.toString())
trace(endQuaternion.toString())
TweenMax.to(plan, 2, tweenObject);
}
function camera_updateCallback():void
{
currentQuaternion = Quaternion.slerp(startQuaternion, endQuaternion,
plan.slerp);
plan.transform.copy3x3(Quaternion.quaternion2Matrix
(currentQuaternion));
}
and i get a kind of lookFrom() = I can tween an object in front of
another one gettin the same rotations.
but the objects are not face to face ...
Before gettin deeper in I'd like to know :
How do you usually do this :
tween a camera in front of an object to a defined distance and rotate
it so that it face it and the target object looks straight on the
screen whatever is its position and rotations ???
... it sound so simple but can't figure out an easy way...
here are the methods added to the quaternion class :
public static function slerp( qa:Quaternion, qb:Quaternion,
alpha:Number ):Quaternion {
var quatSlerp:Quaternion = new Quaternion;
var
angle:Number=qa.w*qb.w+qa.x*qb.x+qa.y*qb.y+qa.z*qb.z;
if (angle<0.0) {
qa.x*=-1.0;
qa.y*=-1.0;
qa.z*=-1.0;
qa.w*=-1.0;
angle*=-1.0;
}
var scale:Number;
var invscale:Number;
if ((angle + 1.0) > 0.000001) {
if ((1.0 - angle) >= 0.000001) {
var theta:Number=Math.acos(angle);
var
invsintheta:Number=1.0/Math.sin(theta);
scale = Math.sin(theta * (1.0-alpha)) *
invsintheta;
invscale=Math.sin(theta*alpha)*invsintheta;
} else {
scale=1.0-alpha;
invscale=alpha;
}
} else {
qb.y=- qa.y;
qb.x=qa.x;
qb.w=- qa.w;
qb.z=qa.z;
scale = Math.sin(Math.PI * (0.5 - alpha));
invscale=Math.sin(Math.PI*alpha);
}
quatSlerp.x = scale * qa.x + invscale * qb.x;
quatSlerp.y = scale * qa.y + invscale * qb.y;
quatSlerp.z = scale * qa.z + invscale * qb.z;
quatSlerp.w = scale * qa.w + invscale * qb.w;
return quatSlerp;
}
static public function createFromMatrix
( matrix:Matrix3D ):Quaternion {
var quat:Quaternion = new Quaternion();
var s:Number;
var q:Array=new Array(4);
var i:int,j:int,k:int;
var tr:Number=matrix.sxx+matrix.syy+matrix.szz;
// check the diagonal
if (tr>0.0) {
s=Math.sqrt(tr+1.0);
quat.w=s/2.0;
s=0.5/s;
quat.x = (matrix.szy - matrix.syz) * s;
quat.y = (matrix.sxz - matrix.szx) * s;
quat.z = (matrix.syx - matrix.sxy) * s;
} else {
// diagonal is negative
var nxt:Array=[1,2,0];
var m:Array = [
[matrix.sxx, matrix.sxy, matrix.sxz, matrix.tx],
[matrix.syx, matrix.syy, matrix.syz, matrix.ty],
[matrix.szx, matrix.szy, matrix.szz, matrix.tz]
];
i=0;
if (m[1][1]>m[0][0]) {
i=1;
}
if (m[2][2]>m[i][i]) {
i=2;
}
j=nxt[i];
k=nxt[j];
s = Math.sqrt((m[i][i] - (m[j][j] + m[k][k])) +
1.0);
q[i]=s*0.5;
if (s!=0.0) {
s=0.5/s;
}
q[3] = (m[k][j] - m[j][k]) * s;
q[j] = (m[j][i] + m[i][j]) * s;
q[k] = (m[k][i] + m[i][k]) * s;
quat.x=q[0];
quat.y=q[1];
quat.z=q[2];
quat.w=q[3];
}
return quat;
}
public static function
quaternion2Matrix(quat:Quaternion):Matrix3D {
var _matrix:Matrix3D=new Matrix3D ;
var xx:Number=quat.x*quat.x;
var xy:Number=quat.x*quat.y;
var xz:Number=quat.x*quat.z;
var xw:Number=quat.x*quat.w;
var yy:Number=quat.y*quat.y;
var yz:Number=quat.y*quat.z;
var yw:Number=quat.y*quat.w;
var zz:Number=quat.z*quat.z;
var zw:Number=quat.z*quat.w;
_matrix.sxx = 1 - 2 * ( yy + zz );
_matrix.sxy = 2 * ( xy - zw );
_matrix.sxz = 2 * ( xz + yw );
_matrix.syx = 2 * ( xy + zw );
_matrix.syy = 1 - 2 * ( xx + zz );
_matrix.syz = 2 * ( yz - xw );
_matrix.szx = 2 * ( xz - yw );
_matrix.szy = 2 * ( yz + xw );
_matrix.szz = 1 - 2 * ( xx + yy );
return _matrix;
}
mainly inspired by papervision use (I know there is a link with
example, but I can't find it)
thanks.