POV-Ray : Newsgroups : povray.advanced-users : One works one doesn't? : Re: One works one doesn't? Server Time
29 Jul 2024 18:26:04 EDT (-0400)
  Re: One works one doesn't?  
From: Dan Johnson
Date: 16 Jun 2001 16:28:03
Message: <3B2D133B.2BDEA666@hotmail.com>
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

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.