PDA

View Full Version : bit shifting to Lscript

LightFreeze
03-24-2008, 02:43 AM
I`m trying to create an importer for this (http://www.newtek.com/forums/showthread.php?t=69662), I have been translating some stuff from the SDK open source tools mocap code into Lscript however I`m struggling to convert the EulOrd and EulGetOrd functions, any suggestions.

#define EulSafe "\000\001\002\000"
#define EulNext "\001\002\000\001"

/* EulGetOrd unpacks all useful information about order simultaneously. */
#define EulGetOrd(ord,i,j,k,h,n,s,f) {unsigned o=ord;f=o&1;o>>=1;s=o&1;o>>=1;\
n=o&1;o>>=1;i=EulSafe[o&3];j=EulNext[i+n];k=EulNext[i+1-n];h=s?k:i;}
/* EulOrd creates an order value between 0 and 23 from 4-tuple choices. */
#define EulOrd(i,p,r,f) (((((((i)<<1)+(p))<<1)+(r))<<1)+(f))

Pomfried
03-24-2008, 04:32 AM
Hi LightFreeze,

basically, if you do a left shift by one you do nothing, but multiplying the value you want to shift by 2 :)
The other way round right shifting by one is equal to dividing by two.

Now the EulGetCord function might be the real problem.
As I don't know any LScript I don't know if there are any better and faster ways to accomplish this... Anyway, here is my hackish work-around idea, which hopefully works:

The first bitwise AND appears to be in "f=o&1;". What it does is only taking the least significant bit of o and assigning it to f (but I guess you know that already :D). So it can only be 1 or 0. And it's 1, if the value of o is odd, otherwise it has to be 0.
In code you can to that by using the modulo operator:
f = o%2;

The next right shift in o >>= 1 should be clear already, so let's move on to the last real problem: "o&3"
Modulo won't work here... OOOH WAIT, IT DOES! :D Hah.. no need to go all that hackish then... o&3 means we want to get the last two bits of the variable o, they can only be up to 3 maximum.
So what do we do? Right! We use the modulo operator again and instead of the divisor of 2 we use 4 ;)

i=EulSafe[o%4];

Phew... learnt something as well now :D
Hopefully this works ;)

LightFreeze
03-24-2008, 05:02 AM
thanks Pomfried you`ve got me over the stopper, heres the lscript functions which I think are getting me the right values

EulOrd: i,p,r,f
{
i*=2;
i+=p;
i*=2;
i+=r;
i*=2;
i+=f;
return(i);
//return((((((i)<<1)+(p))<<1)+(r))<<1)+(f);
}

EulGetOrd: ord
{
/*
#define EulGetOrd(ord,i,j,k,h,n,s,f) {unsigned o=ord;f=o&1;o>>=1;s=o&1;o>>=1;\
n=o&1;o>>=1;i=EulSafe[o&3];j=EulNext[i+n];k=EulNext[i+1-n];h=s?k:i;}
*/
debug();
ret;
o=ord;
f = o%2;
o/=2;
o = int(o);
s = o%2;
o/=2;
o = int(o);
n = o%2;
o/=2;
o = int(o);
i=int(EulSafe[o%4]);
j=int(EulNext[i+n]);
k=int(EulNext[i+1-n]);
//h=s?k:i;
if(h==s)
{
h=k;
}
else
{
h=i;
}
ret[1] = i;
ret[2] = j;
ret[3] = k;
ret[4] = h;
ret[5] = n;
ret[6] = s;
ret[7] = f;
return(ret);
}

I cant tell you if everything is working yet because the i,j,k etc end up as positions in a matrix, like this

sy = sqrt(M[i][j]*M[i][j] + M[i][k]*M[i][k]);
if(sy > 16.0 * FLT_EPSILON)
{
ea[X] = atan2(M[i][j], M[i][k]);
ea[Y] = atan2(sy, M[i][i]);
ea[Z] = atan2(M[j][i], -M[k][i]);
} else {
ea[X] = atan2(-M[j][k], M[j][j]);
ea[Y] = atan2(sy, M[i][i]);
ea[Z] = 0;
and because Lscript arrays start at [1] and not [0] I`ve still to figure out where add to the index.
I`ll probably be back :D

Pomfried
03-24-2008, 05:24 AM
Hehe, so far it looks alright. Only one mistake in your code :D

//h=s?k:i;
if(h==s)
{
h=k;
}
else
{
h=i;
}

h = s
is not the same as
h == 2

The = actually assigns the value ;)
So, h = s?k:i assigns the value k to h if s is non-zero, otherwise it assigns the value i.

LightFreeze
03-24-2008, 05:35 AM
I would never have caught that, thanks

LightFreeze
03-24-2008, 07:13 AM
told you I`d be back, having a problem with this

#define EulSafe "\000\001\002\000"
i=EulSafe[o&3];

I thought this should pull a single character out of the string but if the highest value o&3 can get to is 3 then it will always pull out a zero(I`m assuming the \ are ignored in C as Lscript doesn`t see them in the string) or is that four blocks of three characters, which just occurred to me as I typed this and would make more sense

Pomfried
03-24-2008, 08:15 AM
Actually I'm not quite sure what this does either. Weird way of defining something :D
Just tested it and what it does is return 0, 1, 2 or again 0 for the four possible indices. So it's an array of four integers, but somehow saved as a string (even more confusing because of the \0 at the beginning of the values, which in C/C++ mean the end of a string). Maybe my brain is just playing with me and I will understand it properly in a few moments :P

LightFreeze
03-24-2008, 12:28 PM
I went for the array of four integers as well and everything seems to be working however I went through all 24 different order types and was getting different rotations for them but none would match what I expected, some came close but not close enough. God I Hate Rotations

Pomfried
03-24-2008, 12:44 PM
That's too bad. Things like that can get really frustrating, but I'm sure you will find the mistake ;)
(I guess you are converting the SDK OpenSourceTools helper libraries to lscript? :D)

LightFreeze
03-24-2008, 01:38 PM
yes I pulled some stuff to get an axis angle to eular angles. The biggest IF is the conversion from 0 based arrays to 1 based arrays, heres what I`ve got so far, feel free to throw it in the bin

//-----------------------------------------
// LScript Generic template
//

@version 2.2
@warnings
@script generic
@name "LF_SimToolImp"

EulFrmS = 0;
EulFrmR = 1;
//EulFrm(ord)((unsigned)(ord)&1)
EulRepNo = 0;
EulRepYes = 1;
//EulRep(ord)(((unsigned)(ord)>>1)&1)
EulParEven = 0;
EulParOdd = 1;
//EulPar(ord)(((unsigned)(ord)>>2)&1)

//EulSafe = "/000/001/002/000";
//EulNext = "/001/002/000/001";
EulSafe = @0,1,2,[email protected];
EulNext = @1,2,0,[email protected];
FLT_EPSILON = 0.00000011920929;
// global values go here
PI = 3.14159265359;
X = 0;
Y = 1;
Z = 2;
W = 3;
// rotating axis
EulOrdYXZr = EulOrd(Z,EulParEven,EulRepNo,EulFrmR);
EulOrdZYXr = EulOrd(X,EulParEven,EulRepNo,EulFrmR);
EulOrdYZXr = EulOrd(X,EulParOdd,EulRepNo,EulFrmR);
EulOrdXZYr = EulOrd(Y,EulParEven,EulRepNo,EulFrmR);
EulOrdZXYr = EulOrd(Y,EulParOdd,EulRepNo,EulFrmR);
EulOrdXYZr = EulOrd(Z,EulParOdd,EulRepNo,EulFrmR);

EulOrdXYXr = EulOrd(X,EulParEven,EulRepYes,EulFrmR);
EulOrdXZXr = EulOrd(X,EulParOdd,EulRepYes,EulFrmR);
EulOrdYZYr = EulOrd(Y,EulParEven,EulRepYes,EulFrmR);
EulOrdYXYr = EulOrd(Y,EulParOdd,EulRepYes,EulFrmR);
EulOrdZXZr = EulOrd(Z,EulParEven,EulRepYes,EulFrmR);
EulOrdZYZr = EulOrd(Z,EulParOdd,EulRepYes,EulFrmR);
//order = EulOrdYXZr;//17 - 0 0 0 0 1 1 2
//order = EulOrdZYXr;//1 - 0 0 0 0 1 1 2
//order = EulOrdYZXr;//5 - 0 0 0 0 2 1 2
//order = EulOrdXZYr;//9 - 0 0 0 0 1 1 2
//order = EulOrdZXYr;//13 - 0 0 0 0 2 1 2
//order = EulOrdXYZr;//21 - 0 0 0 0 2 1 2
//order = EulOrdXYXr;
//order = EulOrdXZXr;
//order = EulOrdYZYr;
//order = EulOrdYXYr;
//order = EulOrdZXZr;
//order = EulOrdZYZr;

// static axis
EulOrdXYZs = EulOrd(X,EulParEven,EulRepNo,EulFrmS);
EulOrdXYXs = EulOrd(X,EulParEven,EulRepYes,EulFrmS);
EulOrdXZYs = EulOrd(X,EulParOdd,EulRepNo,EulFrmS);
EulOrdXZXs = EulOrd(X,EulParOdd,EulRepYes,EulFrmS);
EulOrdYZXs = EulOrd(Y,EulParEven,EulRepNo,EulFrmS);
EulOrdYZYs = EulOrd(Y,EulParEven,EulRepYes,EulFrmS);
EulOrdYXZs = EulOrd(Y,EulParOdd,EulRepNo,EulFrmS);
EulOrdYXYs = EulOrd(Y,EulParOdd,EulRepYes,EulFrmS);
EulOrdZXYs = EulOrd(Z,EulParEven,EulRepNo,EulFrmS);
EulOrdZXZs = EulOrd(Z,EulParEven,EulRepYes,EulFrmS);
EulOrdZYXs = EulOrd(Z,EulParOdd,EulRepNo,EulFrmS);
EulOrdZYZs = EulOrd(Z,EulParOdd,EulRepYes,EulFrmS);
//order = EulOrdXYZs;
//order = EulOrdZYXs;
order = EulOrdXYZs;
//order = EulOrdXYXs;
//order = EulOrdXZYs;
//order = EulOrdXZXs;
//order = EulOrdYZXs;//close
//order = EulOrdYZYs;
//order = EulOrdYXZs;//close
//order = EulOrdYXYs;
//order = EulOrdZXYs;
//order = EulOrdZXZs;
//order = EulOrdZYXs;
//order = EulOrdZYZs;
// shifted for 1 based arrays
X = 1;
Y = 2;
Z = 3;
W = 4;

//EulHPB = EulOrdYXZr;

generic
{
// perform all processing here
fname = recall("fname","*.sim");
kf = integer(recall("kf",1));
reqbegin("<Sim Tool Import>");
c1 = ctlfilename("Select simtool file",fname,30,1);
c2 = ctlinteger("Keyframe every",kf);
c3 = ctlinteger("order ",order);
return if !reqpost();

// get requester control values here
fname = getvalue(c1);
kf = getvalue(c2);
store("fname",fname);
store("kf",kf);
reqend();

file=File(fname,"r");
if(file == nil) error(string("Could not open sim File!(",fname,")"));
file.open(fname,"r");
arr = parse(" ",txt);
frms = arr[2].asInt();
arr = parse(" ",txt);
fps = arr[2].asInt();

//debug();
while(true)
{
if(file.eof())break;
arr = parse(" ",txt);
currob = arr[2].asStr();
//info(currob);
mesh = Mesh(currob);
cid = mesh.id;
mesh = Mesh("target");
tid = mesh.id;
vec;
for(i=1;i<4;i++)//positions
{
for(j=1;j<=frms;j++)
{
arr = parse(" ",txt);
vec[i][j] = arr[2].asNum();
}
}
axan;
for(j=1;j<=frms;j++)
{
//debug();
txt = file.read();// axis and angle
arr = parse(" ,]",txt);
ax = normalize(<-arr[2].asNum(),arr[3].asNum(),-arr[4].asNum()>);
arr = parse(" ,",txt);
rot = <arr[2].asNum(),arr[3].asNum(),arr[4].asNum()>;
//nrot = axanToEul(ax,an);
//nrot = vectodeg(ax,an);
axan[1][j] = ax;
axan[2][j] = an;
axan[3][j] = rot;
}
SelectItem(cid);
//debug();
scl = <10,10,10>;
for(j=1;j<=frms;j+=kf)//pos to vec
{
GoToFrame(j);
pos = <-vec[1][j],vec[2][j],-vec[3][j]>;
Position(pos);
//rot = toEuler(axan[1][j],axan[2][j]);
//rot = <-axan[3][j].y,-axan[3][j].x,0>;
//vectodeg(axan[3][j]);
rot = getRot(axan[1][j],axan[2][j]);
//rot = shuffle(axan[3][j]);
//rot2 = <rot.y,0,0>;
Rotation(rot);
}
SelectItem(tid);
for(j=1;j<=frms;j+=kf)//pos to vec
{
GoToFrame(j);
pos = <-vec[1][j],vec[2][j],-vec[3][j]>;
Position(pos+axan[1][j]);
//Rotation();
}
//info(pos);

}

//debug();
file.close();
dat = EulGetOrd(order);

}

getRot: ax,an
{
quat = LWQUAT_QFromAngAxis(ax,an);
rea = LWEUL_fromQuat(quat,order);//radian euler, order Global
rot = <deg(rea[1]),deg(rea[2]),deg(rea[3])>;
return(rot);
}
atan2: y,x
{

PI = 3.14159265359;
HPI = PI * 0.5;
TPI = PI * 2.0;
if((x >= 0) and(y == 0))return(0);
if((x < 0) and(y == 0))return(PI);
h = sqrt(x*x+y*y);
x1 = abs(x);
y1 = abs(y);
at = asin(y/h);
if((x <= 0) and(y > 0))//:#done
{
at = PI - at;
}

//if(at<0)at+=TPI;
return(at);
}

EulOrd: i,p,r,f
{
i*=2;
i+=p;
i*=2;
i+=r;
i*=2;
i+=f;
return(i);
//return((((((i)<<1)+(p))<<1)+(r))<<1)+(f);
}
// EulGetOrd unpacks all useful information about order simultaneously.
/*
LScript now provides support for binary-formatted numbers. These numbers are prefixed by the
"0b" character sequence, and can contain 1-32 binary digits(0 or 1).
...
t = 0b1001; // t holds 9
*/

EulGetOrd: ord
{
/*
#define EulGetOrd(ord,i,j,k,h,n,s,f) {unsigned o=ord;f=o&1;o>>=1;s=o&1;o>>=1;\
n=o&1;o>>=1;i=EulSafe[o&3];j=EulNext[i+n];k=EulNext[i+1-n];h=s?k:i;}
*/
//debug();
ret;
o=ord;
f = o%2;
//f+=1;
o/=2;
o = int(o);
s = o%2;
//s+=1;
o/=2;
o = int(o);
n = o%2;

o/=2;
o = int(o);
i=int(EulSafe[o%4+1]);
j=int(EulNext[i+n+1]);

k=int(EulNext[i+1-n+1]);
//n+=1;
//h=s?k:i;
if(s<>0)
{
h=k;
}
else
{
h=i;
}
ret[1] = i;
ret[2] = j;
ret[3] = k;
ret[4] = h;
ret[5] = n;
ret[6] = s;
ret[7] = f;
return(ret);
}
/* --- Compute equivalent quaternion from[angle,axis] representation */
LWQUAT_QFromAngAxis: ax,ang
{
axis[1] = ax.x;
axis[2] = ax.y;
axis[3] = ax.z;
omega = ang * 0.5;
s = sin(omega);
for(i=1; i<4; i++) q[i] = s*axis[i];
q[4] = cos(omega);
return(q);
}

/* Convert quaternion to Euler angles(in radians). */
LWEUL_fromQuat: q,order
{
//LWFMatrix4 M;
M;
Nq = q[X]*q[X]+q[Y]*q[Y]+q[Z]*q[Z]+q[W]*q[W];
//s =(Nq > 0.0) ?(2.0 / Nq) : 0.0;
if(Nq >0.0)
{
s = 2.0 / Nq;
}
else
{
s = 0.0;
}
xs = q[X]*s;
ys = q[Y]*s;
zs = q[Z]*s;
wx = q[W]*xs;
wy = q[W]*ys;
wz = q[W]*zs;
xx = q[X]*xs;
xy = q[X]*ys;
xz = q[X]*zs;
yy = q[Y]*ys;
yz = q[Y]*zs;
zz = q[Z]*zs;
// matrix positions are shifted because of 1 based arrays in Lscript
M[X][X] = 1.0 -(yy + zz); M[X][Y] = xy - wz; M[X][Z] = xz + wy;
M[Y][X] = xy + wz; M[Y][Y] = 1.0 -(xx + zz); M[Y][Z] = yz - wx;
M[Z][X] = xz - wy; M[Z][Y] = yz + wx; M[Z][Z] = 1.0 -(xx + yy);
M[W][X]=M[W][Y]=M[W][Z]=M[X][W]=M[Y][W]=M[Z][W]=0.0; M[W][W]=1.0;
ea = LWEUL_fromMatrix(M, order);
return(ea);
}

LWEUL_fromMatrix: M,order
{
ea;
//int i,j,k,h,n,s,f;
ret = EulGetOrd(order);
//shifting matrix positions to match generated, only i,j,k
i = ret[1];
i+=1;
j = ret[2];
j+=1;
k = ret[3];
k+=1;
h = ret[4];
//h+=1;
n = ret[5];
//n+=1;
s = ret[6];
//s+=1;
f = ret[7];
//f+=1;

if(s==EulRepYes)
{
sy = sqrt(M[i][j]*M[i][j] + M[i][k]*M[i][k]);
if(sy > 16.0 * FLT_EPSILON)
{
ea[X] = atan2(M[i][j], M[i][k]);
ea[Y] = atan2(sy, M[i][i]);
ea[Z] = atan2(M[j][i], -M[k][i]);
} else {
ea[X] = atan2(-M[j][k], M[j][j]);
ea[Y] = atan2(sy, M[i][i]);
ea[Z] = 0;
}
} else {
cy = sqrt(M[i][i]*M[i][i] + M[j][i]*M[j][i]);
if(cy > 16.0 * FLT_EPSILON)
{
ea[X] = atan2(M[k][j], M[k][k]);
ea[Y] = atan2(-M[k][i], cy);
ea[Z] = atan2(M[j][i], M[i][i]);
} else {
ea[X] = atan2(-M[j][k], M[j][j]);
ea[Y] = atan2(-M[k][i], cy);
ea[Z] = 0;
}
}
if(n==EulParOdd) {ea[X] = -ea[X]; ea[Y] = - ea[Y]; ea[Z] = -ea[Z];}
if(f==EulFrmR) {t = ea[X]; ea[X] = ea[Z]; ea[Z] = t;}
ea[W] = order;
return(ea);
}