|
|
Rune wrote:
>
> Where and how is the 4D vector returned by the macro used? Can you provide
> an example? That might help people helping you (though I probably won't be
> able to help you myself, as 4D vectors are not my area).
>
> Rune
> --
> 3D images and anims, include files, tutorials and more:
> Rune's World: http://rsj.mobilixnet.dk (updated May 10)
> POV-Ray Users: http://rsj.mobilixnet.dk/povrayusers/
> POV-Ray Webring: http://webring.povray.co.uk
OK then here is all of my 4D vector functions. Another one is
generating a bug that is even more frustrating.
The H2T_sr function dies most of the time it is given a 180 degree
rotation such as.
box{<0,0,0>,<1,1,1> Q_matrix(H2T_sr(x,-x)) pigment{Red}}
On with the code
// Begin Code
/*#macro Quaternion(Angle,Vector) // creates a normalized rotation
quaternion... angle in radians
#if (vlength(Vector)=0)
#warning "0 vector not allowed\nUsing identity Quaternion"
<1,0,0,0>
#else
#local A = Angle/2;
#local V = sin(A)*vnormalize(Vector);
<cos(A),V.x,V.y,V.z>
#end
#end*/
#macro Quaternion(Angle,Vector) //Old version
#if (vlength(Vector)=0) #warning "0 vector not allowed" #end
#local A = Angle/2;
#local V = sin(A)*vnormalize(Vector);
<cos(A),V.x,V.y,V.z>
#end
#macro Q_conjugate(Q) // the conjugate of a quaternion
<Q.x,-Q.y,-Q.z,-Q.t> // will rotate around the same axis in the
opposite direction
#end
#macro Q_axis (Quat) // returns normalized axis of Quaternion
#local V = vnormalize (<Quat.y,Quat.z,Quat.t>);
#if (vlength(V) = 0)
#warning "Degenerate Axis"
#end
V
#end
#macro Q_angle(Quat) // returns angle in radians of Quaternion
acos(Quat.x)
#end
#macro Q_multiply(P,Q) // multiplies two quaternions
#local P0 = P.x;
#local Pv = <P.y,P.z,P.t>;
#local Q0 = Q.x;
#local Qv = <Q.y,Q.z,Q.t>;
#local PQ0 = P0*Q0 - vdot(Pv,Qv);
#local PQv = P0*Qv + Q0*Pv + vcross(Pv,Qv);
<PQ0,PQv.x,PQv.y,PQv.z>
#end
#macro Q_matrix_array (Q) // converts a quaternion into a matrix
#local Q0 = Q.x;
#local Q1 = Q.y;
#local Q2 = Q.z;
#local Q3 = Q.t;
#local QT = 2*pow(Q0,2)-1;
array[12]
{QT+2*pow(Q1,2),2*(Q1*Q2+Q0*Q3),2*(Q1*Q3-Q0*Q2),
2*(Q1*Q2-Q0*Q3),QT+2*pow(Q2,2),2*(Q2*Q3+Q0*Q1),
2*(Q1*Q3+Q0*Q2),2*(Q2*Q3-Q0*Q1),QT+2*pow(Q3,2),
0,0,0}
#end
#macro Rotate_displace (Q,V) // rotate using Quaternion displace using
vector, returns matrix array
#local Mat = Q_matrix_array (Q);
#local Mat[9] = V.x;
#local Mat[10] = V.y;
#local Mat[11] = V.z;
Mat
#end
#macro Matrix_2_matrix (M) // Creates a translation matrix from matrix
array
matrix<M[0],M[1],M[2],M[3],M[4],M[5],M[6],M[7],M[8],M[9],M[10],M[11]>
#end
#macro Matrix_mult (M1,M2) // multiplys two matrices
#local R1 = <M1[0],M1[1],M1[2],0>; // matrix 1 rows
#local R2 = <M1[3],M1[4],M1[5],0>;
#local R3 = <M1[6],M1[7],M1[8],0>;
#local R4 = <M1[9],M1[10],M1[11],0>;
#local C1 = <M2[0],M2[3],M2[6],M2[9]>; // matrix 2 columns
#local C1 = <M2[1],M2[4],M2[7],M2[10]>;
#local C1 = <M2[2],M2[5],M2[8],M2[11]>;
#local M = array[12] // The calculations
{vdot(R1,C1),vdot(R1,C2),vdot(R1,C3),
vdot(R2,C1),vdot(R2,C2),vdot(R2,C3),
vdot(R3,C1),vdot(R3,C2),vdot(R3,C3),
vdot(R4,C1),vdot(R4,C2),vdot(R4,C3)}
M
#end
#macro V_matrix (V,M)// V is a vector M is a 12 element array in the
same pattern as a matrix
#local Vx = V.x*M[0] + V.y*M[3] + V.z*M[6] + M[9];
#local Vy = V.x*M[1] + V.y*M[4] + V.z*M[7] + M[10];
#local Vz = V.x*M[2] + V.y*M[5] + V.z*M[8] + M[11];
<Vx,Vy,Vz>
#end
#macro VQ(V,Q)// applies a Quaternion oporator to a vector
/*#local Qs = Q.x; // Last line
replaced this code wich misteriously does not work
#local Qv = <Q.y,Q.z,Q.t>;
(((2*Qs*Qs)-1)*v + 2*vdot(Qv,V)*Qv + 2*Qs*vcross(Qv,V))*/
V_matrix (V,Q_matrix_array (Q)) // less
efficient way.
#end
#macro Q_matrix (Q) // converts a quaternion into a matrix
#local Q0 = Q.x;
#local Q1 = Q.y;
#local Q2 = Q.z;
#local Q3 = Q.t;
#local QT = 2*pow(Q0,2)-1;
matrix
<QT+2*pow(Q1,2),2*(Q1*Q2+Q0*Q3),2*(Q1*Q3-Q0*Q2),
2*(Q1*Q2-Q0*Q3),QT+2*pow(Q2,2),2*(Q2*Q3+Q0*Q1),
2*(Q1*Q3+Q0*Q2),2*(Q2*Q3-Q0*Q1),QT+2*pow(Q3,2),
0,0,0>
#end
#macro Q_half_turn(V) //180 degree rotation about vector
#local V = vnormalize(V);
<0,V.x,V.y,V.z>
#end
// Here to There simple rotation version
#macro H2T_sr (V1,V2) // rotates object pointing at V1 so that it points
at V2
#if ((vlength(V1) = 0) | (vlength (V2) = 0) |
(Same_test(vnormalize(V1),vnormalize(V2))))
#local Qout = <1,0,0,0>; // if either input vector is
zero, or angle between them is zero
#else // no rotation needed output
identity quaternion
#if (vlength (vcross(V1,V2)) = 0) // see if vectors point
in opposite directions
#if (vlength(vcross(<1,1,1>,V1))!=0) // if V1 is not
parralel to <1,1,1>
#local Qout = Q_half_turn(<1,1,1>-Proj(<1,1,1>,V1));//
Proj(<1,1,1>,V1) is parralel to V1 (<1,1,1>-Proj(<1,1,1>,V1))
#else //
should be perpendicular
#local Qout = Q_half_turn(<1,0,-1>);
#end
#else
#local Angle = acos(vdot(V1,V2)/(vlength(V1)*vlength(V2)));
#local Axis = vcross (V1,V2);
#local Qout = Quaternion(Angle,Axis);
#end
#end
Qout
#end
// Here to There general rotation version
#macro H2T_r(U1,U2,V1,V2)
#local U = U2-U1;
#local U = U-Proj(U,U1);
#local V = V2-V1;
#local V = V-Proj(V,V1);
#local Q1 = H2T_sr (U1,V1);
#local Vr = VQ(U,Q1);
#if (vlength(vcross(Vr,V)) = 0)
#if (vlength(vnormalize(Vr)-vnormalize(V))=0)
#local Q2 = <1,0,0,0>;
#else
#local Q2 = Q_half_turn(V1);
#end
#else
#local Q2 = H2T_sr (Vr,V);
#end
Q_multiply(Q2,Q1)
#end
#macro R(Axis,Angle) // rotates around axis by angle... angle in radians
Q_matrix (Quaternion(Angle,Axis))
#end
// End Code
--
Dan Johnson
http://www.geocities.com/zapob
Post a reply to this message
|
|
|
|
Dan Johnson wrote:
> Fixed all the other known bugs in my code this weekend. I still don't
> know why the first one of these doesn't work, and the second one does.
>
> <snip>
> > /*#macro Quaternion(Angle,Vector) // creates a normalized rotation
> > quaternion... angle in radians
> > #if (vlength(Vector)=0)
> > #warning "0 vector not allowed\nUsing identity Quaternion"
> > <1,0,0,0>
> > #else
> > #local A = Angle/2;
> > #local V = sin(A)*vnormalize(Vector);
> > <cos(A),V.x,V.y,V.z>
> > #end
> > #end*/
> > #macro Quaternion(Angle,Vector) //Old version
> > #if (vlength(Vector)=0) #warning "0 vector not allowed" #end
> > #local A = Angle/2;
> > #local V = sin(A)*vnormalize(Vector);
> > <cos(A),V.x,V.y,V.z>
> > #end
> <snip>
Ok, the problem is that macros aren't full subroutines like you might
expect. For example
#macro example(a)
#if (a=0)
<1,0,0,0>
#else
<0,0,0,0>
#end
#end
Parses into this when the macro is evaluated...
#if (a=0)
<1,0,0,0>
#else
<0,0,0,0>
#end
And at this level everything needs to be legal, it chokes.
The solution is to dump everything into #locals..
#macro Quaternion(Angle,Vector) // creates a normalized rotation
quaternion... angle in radians
#if (vlength(Vector)=0)
#warning "0 vector not allowed\nUsing identity Quaternion"
#local A = 1;
#local V = <0,0,0>;
#else
#local A = cos(Angle/2);
#local V = sin(Angle/2)*vnormalize(Vector);
#end
<A,V.x,V.y,V.z>
#end
----- Tim Attwood -----
Post a reply to this message
|
|