/**
* Copyright mutantleg ( http://wonderfl.net/user/mutantleg )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/6HYm
*/
package {
import flash.utils.Dictionary;
import flash.events.Event;
import flash.display.Sprite;
public class FlashTest extends Sprite {
public function FlashTest() {
myChar = new xChar();
dictBone = new Dictionary();
var a:xBone;
//second thought.. adding new bones will need some rethinking
//0
a = addBone(myChar); dictBone["root"] = a;
//1
a = addBone(myChar); a.pos.x=32; a.pos.y=32; dictBone["leg1a"] = a;
a.parent = 0; a.depth = 1;
//2
a = addBone(myChar); a.pos.x=0; a.pos.y=32; dictBone["leg2a"] = a;
a.parent = 1; a.depth = 2;
//3
a = addBone(myChar); a.pos.x=0; a.pos.y=32; dictBone["leg3a"] = a;
a.parent = 2; a.depth = 3;
//4
a = addBone(myChar); a.pos.x=0; a.pos.z=-24; dictBone["leg4a"] = a;
a.parent = 3; a.depth = 4;
//5
a = addBone(myChar); a.pos.x=-32; a.pos.y=32; dictBone["leg1b"] = a;
a.parent = 0; a.depth = 1;
//6
a = addBone(myChar); a.pos.x=0; a.pos.y=32; dictBone["leg2b"] = a;
a.parent = 5; a.depth = 2;
//7
a = addBone(myChar); a.pos.x=0; a.pos.y=32; dictBone["leg3b"] = a;
a.parent = 6; a.depth = 3;
//8
a = addBone(myChar); a.pos.x=0; a.pos.z=-24; dictBone["leg4b"] = a;
a.parent = 7; a.depth = 4;
myChar.update();
stage.addEventListener(Event.ENTER_FRAME, onEnter);
}//ctor
public var dictBone:Dictionary;
public var myChar:xChar;
public function addBone(ch:xChar):xBone
{
var a:xBone; a = new xBone();
a.id = ch.vecBone.length;
ch.vecBone.push(a);
return a;
} //addbone
public var gt:int = 0;
public function onEnter(e:Event):void
{
graphics.clear();
graphics.lineStyle(2, 0);
var sx:Number; var sy:Number;
sx = 230; sy = 230;
var a:xBone; var p:xBone;
var vec:Vector.<xBone>;
var num:int; var i:int;
var ang:Number;
var xang:Number;
ang = gt * 0.05;
xang = Math.sin(ang) * Math.cos(ang);
a = dictBone["root"];
a.ori.reset(); //a.ori.rotAxis(-xang, 2);
a.pos.y = Math.sin(Math.abs(xang)*-2)*64;
//still needs tweaks
//when it goes down it should do this
//but im too tired
// ** **\ \ *** |
// |****/ |**** \ ****|
// | | \/
a = dictBone["leg1a"];
a.ori.reset(); a.ori.rotAxis(xang*3,0);
a.pos.z = xang*32;
a = dictBone["leg2a"];
a.ori.reset(); a.ori.rotAxis(xang+1,0);
a = dictBone["leg1b"];
a.ori.reset(); a.ori.rotAxis(-xang*3,0);
a.pos.z = -xang*32;
a = dictBone["leg2b"];
a.ori.reset(); a.ori.rotAxis(-xang+1,0);
myChar.ori.reset();
myChar.ori.rotAxis(0.9, 0);
//myChar.ori.rotAxis(0.4, 2);
// myChar.ori.rotAxis(1.5, 1);
myChar.ori.rotAxis(gt*0.02, 1);
myChar.update();
vec = myChar.vecBone;
num = vec.length;
a = vec[0];
graphics.lineStyle();
graphics.beginFill(0, 0.2);
//graphics.drawCircle(myChar.pos.x+sx, myChar.pos.y+sy+64,32);
graphics.drawEllipse(myChar.pos.x+sx-32,myChar.pos.y+sy+80-16,64,32);
graphics.endFill();
graphics.lineStyle(4,0);
for (i = 0; i < num; i++)
{
a = vec[i];
graphics.drawCircle(a.wpos.x+sx,a.wpos.y+sy, 8);
if (a.depth <= 0) { continue; }
p = vec[a.parent];
graphics.moveTo(p.wpos.x+sx, p.wpos.y+sy);
graphics.lineTo(a.wpos.x+sx, a.wpos.y+sy);
}//nexti
a = vec[0];
graphics.beginFill(0xFF, 0.5);
graphics.drawCircle(a.wpos.x+sx,a.wpos.y+sy, 32);
graphics.endFill();
gt += 1;
}//onenter
}//classend
}
import flash.geom.Matrix3D;
internal class xChar
{
public var pos:xVec = new xVec();
public var ori:xQuat = new xQuat();
public var scale:xVec = new xVec(1, 1, 1);
public var baseMat:Vector.<Number> = new Vector.<Number>(16, false);
public var vecBone:Vector.<xBone> = new Vector.<xBone>(0, false);
public var tempMat:Vector.<Number> = Vector.<Number>([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
public function update():void
{
var i:int; var num:int; var a:xBone; var p:xBone;
var rx:Number; var ry:Number; var rz:Number;
var vec:Vector.<xBone>; var mat:Vector.<Number>;
var pmat:Vector.<Number>; var pori:xQuat;
mat = baseMat;
ori.setVec(mat);
mat[12] = pos.x; mat[13] = pos.y; mat[14] = pos.z;
mat[0] *= scale.x; mat[1] *= scale.x; mat[2] *= scale.x;
mat[4] *= scale.y; mat[5] *= scale.y; mat[6] *= scale.y;
mat[8] *= scale.z; mat[9] *= scale.z; mat[10] *=scale.z;
vec = vecBone; num = vec.length;
//bone vector is expected to be sorted by depth at this point
for (i = 0; i < num; i++)
{
a = vec[i];
if (a.depth <= 0) { pmat = baseMat; pori = ori; } //no parent bone: use root as parent
else { p = vec[a.parent]; pmat = p.transMat; pori = p.wori; }
mat = tempMat; a.ori.setVec(mat);
mat[12] = a.pos.x; mat[13] = a.pos.y; mat[14] = a.pos.z;
mat[0] *= a.scale.x; mat[1] *= a.scale.x; mat[2] *= a.scale.x;
mat[4] *= a.scale.y; mat[5] *= a.scale.y; mat[6] *= a.scale.y;
mat[8] *= a.scale.z; mat[9] *= a.scale.z; mat[10] *= a.scale.z;
multMatrix(pmat, tempMat, a.transMat);
//ori and position for attachments (world transform)
a.wori.copyQuat(pori);
a.wori.mul(a.ori);
a.wori.normalise();
a.wpos.setValue(a.transMat[12], a.transMat[13], a.transMat[14]);
}//nexti
}//update
//only works of 4x4 matrices (16 Number)
public function multMatrix(a:Vector.<Number>, b:Vector.<Number>, r:Vector.<Number>):void
{
var i:int;
for (i = 0; i < 16; i += 4)
{
r[i] = a[0] * b[i] + a[4] * b[i + 1] + a[8] * b[i + 2] + a[12] * b[i + 3];
r[i + 1] = a[1] * b[i] + a[5] * b[i + 1] + a[9] * b[i + 2] + a[13] * b[i + 3];
r[i + 2] = a[2] * b[i] + a[6] * b[i + 1] + a[10] * b[i + 2] + a[14] * b[i + 3];
r[i + 3] = a[3] * b[i] + a[7] * b[i + 1] + a[11] * b[i + 2] + a[15] * b[i + 3];
}//nexti
}//multmatrix
}//xchar
internal class xBone
{
public var pos:xVec = new xVec(); public var ori:xQuat = new xQuat(); //local pos
public var wpos:xVec = new xVec(); public var wori:xQuat = new xQuat(); //world pos
public var scale:xVec = new xVec(1,1,1); //scale
public var transMat:Vector.<Number> = new Vector.<Number>(16, false);
public var parent:int = 0;
public var id:int = 0;
public var depth:int = 0;
public var spec:int = 0;
}//xbone
internal class xVec
{
public var x:Number = 0; public var y:Number = 0; public var z:Number = 0;
public function xVec(ax:Number=0,ay:Number=0,az:Number=0)
{ x = ax; y = ay; z = az; }
public function setValue(ax:Number=0,ay:Number=0,az:Number=0):void
{ x = ax; y = ay; z = az; }
}//xvec
internal class xQuat
{
public var x:Number = 0; public var y:Number = 0;
public var z:Number = 0; public var w:Number = 1;
public function reset():void { x = 0; y = 0; z = 0; w = 1;}
public function copyQuat(a:xQuat):void { x=a.x; y=a.y; z=a.z; w=a.w; }
public function normalise():void
{
var mag:Number; mag = (x * x) + (y * y) + (z * z) + (w * w);
if (mag == 1.0) return; //already normal
if (mag == 0) { x = 0; y = 0; z = 0; w = 1; return; }
mag = 1.0 / Math.sqrt(mag);
x *= mag; y *= mag; z *= mag; w *= mag;
}//norm
public function mul(a:xQuat):void
{
var tx:Number; var ty:Number; var tz:Number; var tw:Number;
tx = (w * a.x + x * a.w + y * a.z - z * a.y); ty = (w * a.y + y * a.w + z * a.x - x * a.z);
tz = (w * a.z + z * a.w + x * a.y - y * a.x); tw = (w * a.w - x * a.x - y * a.y - z * a.z);
x = tx; y = ty; z = tz; w = tw;
}//mul
//0 x 1 y 2 z
public function rotAxis(ang:Number, xyz:int=0):void
{
ang *= 0.5;
var ax:Number; var ay:Number; var az:Number; var aw:Number;
var tx:Number; var ty:Number; var tz:Number; var tw:Number;
ax = xyz==0? Math.sin(ang):0; ay = xyz==1? Math.sin(ang):0; az = xyz==2? Math.sin(ang):0; aw = Math.cos(ang);
tx = (w * ax + x * aw + y * az - z * ay); ty = (w * ay + y * aw + z * ax - x * az);
tz = (w * az + z * aw + x * ay - y * ax); tw = (w * aw - x * ax - y * ay - z * az);
x = tx; y = ty; z = tz; w = tw;
normalise();
}//rotaxis
public function nlerp(q1:xQuat, q2:xQuat, t:Number):void
{
var dot:Number; var b:Number; var rx:Number; var ry:Number; var rz:Number; var rw:Number;
dot = q1.w*q2.w + q1.x*q2.x + q1.y*q2.y + q1.z * q2.z;
b = 1.0 - t; if (dot < 0) { t = -t;}
w = b * q1.w + t * q2.w; x = b * q1.x + t * q2.x; y = b * q1.y + t * q2.y; z = b * q1.z + t * q2.z;
}//nlerp
public function setVec(vec:Vector.<Number>):void
{
var xx:Number = x * x; var xy:Number = x * y; var xz:Number = x * z; var xw:Number = x * w;
var yy:Number = y * y; var yz:Number = y * z; var yw:Number = y * w;
var zz:Number = z * z; var zw:Number = z * w;
vec[3] = vec[7] = vec[11] = vec[12] = vec[13] = vec[14] = 0.0; vec[15] = 1.0;
vec[0] = 1.0 - 2.0 * ( yy + zz ); vec[4] = 2.0 * ( xy - zw ); vec[8] = 2.0 * ( xz + yw );
vec[1] = 2.0 * ( xy + zw ) ; vec[5] = 1.0 - 2.0 * ( xx + zz ) ; vec[9] = 2.0 * ( yz - xw ) ;
vec[2] = 2.0 * ( xz - yw ); vec[6] = 2.0 * ( yz + xw ); vec[10] = 1.0 - 2.0 * ( xx + yy );
}//setvec
public static var tempVec:Vector.<Number> = new Vector.<Number>(16, false);
public function setMatrix(m:Matrix3D):void { setVec(tempVec); m.rawData = tempVec; }
}//xquat