/[hegemonie]/hegemonie/Common/Quaternion.m
ViewVC logotype

Diff of /hegemonie/Common/Quaternion.m

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.2 by dam, Mon Jun 30 16:23:41 2003 UTC revision 1.3 by dam, Fri Jul 25 21:01:56 2003 UTC
# Line 39  Line 39 
39    
40  @implementation Quaternion  @implementation Quaternion
41    
 /*  
  * This method builds an instance of Quaternion,  
  * with all the attributes initialised at 0  
  */  
 - (id) init  
 {  
   self = [super init];  
     
   if (self != nil)  
     {  
       _x = _y = _z = 0.0f;  
       _w = 1.0f;  
     }  
   return self;  
 }  
42    
43  /*  /*
44   * This method builds an instance of Quaternion,   * This method builds an instance of Quaternion,
45   * with all the attributes initialised with the parameters   * with all the attributes initialised with the parameters
46   */   */
47  - (id) initWithValuesX: (float) x  - (id) initWithValuesX: (float)x
48                       Y: (float) y                       Y: (float)y
49                       Z: (float) z                       Z: (float)z
50                       W: (float) w                       W: (float)w
51  {  {
52    self = [super init];    self = [super init];  
     
53    if (self != nil)    if (self != nil)
54      {      {
55        _x = x;        _x = x;
# Line 73  Line 57 
57        _z = z;        _z = z;
58        _w = w;        _w = w;
59      }      }
   return self;  
 }  
   
60    
61  /*    return self;
  * Frees memory.  
  */  
 - (void) dealloc {  
   if (_matrix)  
     free (_matrix);  
   [super dealloc];  
62  }  }
63    
   
64  /* This method builds an instance of Quaternion,  /* This method builds an instance of Quaternion,
65   * by converting the matrix in parameter   * by converting the matrix in parameter
66   * This matrix must be a 4x4 matrix, otherwise the function will crash.   * This matrix must be a 4x4 matrix, otherwise the function will crash.
67   */   */
68  - (id) initWithMatrix: (float *)matrix  - (id) initWithRotation: (Matrix)rotation
69  {  {
70    NSParameterAssert (matrix);    NSParameterAssert (rotation);
71        
72    self = [super init];    self = [super init];
     
73    if (self != nil)    if (self != nil)
74      {      {
75        float trace = matrix[0] + matrix[5] + matrix[10] + 1;        float trace = rotation[0] + rotation[5] + rotation[10] + 1;
76        float scale = 0.0f;        float scale = 0.0f;
77                
78        if (trace > 0 + DELTA)        if (trace > 0 + DELTA)
79          {          {
80            scale = (float) (sqrt (trace) * 2);            scale = (float)(sqrt (trace) * 2);
81                        
82            _x = (matrix[9] - matrix[6] ) / scale;            _x = (rotation[9] - rotation[6]) / scale;
83            _y = (matrix[2] - matrix[8] ) / scale;            _y = (rotation[2] - rotation[8]) / scale;
84            _z = (matrix[4] - matrix[1] ) / scale;            _z = (rotation[4] - rotation[1]) / scale;
85            _w = 0.25f * scale;            _w = 0.25f * scale;
86          }          }
87        else        else
88          {          {
89            if (matrix[0] > matrix[5] && matrix[0] > matrix[10])              if (rotation[0] > rotation[5] && rotation[0] > rotation[10])  
90              {                {  
91                scale =                scale =
92                  (float) sqrt (1.0f + matrix[0] - matrix[5] - matrix[10]) *2.0f;                  (float)sqrt (1.0f + rotation[0] - rotation[5] - rotation[10])
93                    * 2.0f;
94                                
95                _x = 0.25f * scale;                _x = 0.25f * scale;
96                _y = (matrix[4] + matrix[1] ) / scale;                _y = (rotation[4] + rotation[1]) / scale;
97                _z = (matrix[2] + matrix[8] ) / scale;                _z = (rotation[2] + rotation[8]) / scale;
98                _w = (matrix[9] - matrix[6] ) / scale;                _w = (rotation[9] - rotation[6]) / scale;
99              }              }
100            else if (matrix[5] > matrix[10])            else if (rotation[5] > rotation[10])
101              {              {
102                scale =                scale =
103                  (float) sqrt (1.0f + matrix[5] - matrix[0] - matrix[10]) *2.0f;                  (float)sqrt (1.0f + rotation[5] - rotation[0] - rotation[10])
104                    * 2.0f;
105                                
106                _x = (matrix[4] + matrix[1]) / scale;                _x = (rotation[4] + rotation[1]) / scale;
107                _y = 0.25f * scale;                _y = 0.25f * scale;
108                _z = (matrix[9] + matrix[6]) / scale;                _z = (rotation[9] + rotation[6]) / scale;
109                _w = (matrix[2] - matrix[8]) / scale;                _w = (rotation[2] - rotation[8]) / scale;
110              }              }
111            else            else
112              {                {  
113                scale =                scale =
114                  (float) sqrt (1.0f + matrix[10] - matrix[0] - matrix[5]) *2.0f;                  (float)sqrt (1.0f + rotation[10] - rotation[0] - rotation[5])
115                    * 2.0f;
116                                
117                _x = (matrix[2] + matrix[8]) / scale;                _x = (rotation[2] + rotation[8]) / scale;
118                _y = (matrix[9] + matrix[6]) / scale;                _y = (rotation[9] + rotation[6]) / scale;
119                _z = 0.25f * scale;                _z = 0.25f * scale;
120                _w = (matrix[4] - matrix[1]) / scale;                _w = (rotation[4] - rotation[1]) / scale;
121              }              }
122          }          }
123      }      }
124    
125    return self;    return self;
126  }  }
127    
128  /*  /*
129   * This method returns the matrix 4x4 corresponding to the quaternion.   * This method returns the rotation matrix 4x4 corresponding to the quaternion.
130   * So it converts a quaternion to a matrix 4x4.   * So it converts a quaternion to a matrix 4x4.
131   */   */
132  - (float *) createMatrix  - (void) convertToRotation: (Matrix)rotation
133  {  {
   if ((_matrix = (float *) malloc (16 * sizeof (float))) == NULL)  
     {  
       fprintf (stderr, "It ' s impossible to create a 4x4 matrix: "  
                "memory allocation has failed.\n");  
       exit (-1);  
     }  
     
134    float xx = _x * _x;    float xx = _x * _x;
135    float xy = _x * _y;    float xy = _x * _y;
136    float xz = _x * _z;    float xz = _x * _z;
# Line 172  Line 142 
142    float zw = _z * _w;    float zw = _z * _w;
143        
144    /* first row */    /* first row */
145    _matrix[0]  = 1.0f - 2.0f * ( yy + zz );    rotation[0]  = 1.0f - 2.0f * (yy + zz);
146    _matrix[1]  = 2.0f * ( xy - zw );    rotation[1]  = 2.0f * (xy - zw);
147    _matrix[2]  = 2.0f * ( xz + yw );    rotation[2]  = 2.0f * (xz + yw);
148    _matrix[3]  = 0;    rotation[3]  = 0;
149        
150    /* second row */    /* second row */
151    _matrix[4]  = 2.0f * ( xy + zw );    rotation[4]  = 2.0f * (xy + zw);
152    _matrix[5]  = 1.0f - 2.0f * ( xx + zz );    rotation[5]  = 1.0f - 2.0f * (xx + zz);
153    _matrix[6]  = 2.0f * ( yz - xw );    rotation[6]  = 2.0f * (yz - xw);
154    _matrix[7]  = 0;    rotation[7]  = 0;
155        
156    /* third row */    /* third row */
157    _matrix[8]  = 2.0f * ( xz - yw );    rotation[8]  = 2.0f * (xz - yw);
158    _matrix[9]  = 2.0f * ( yz + xw );    rotation[9]  = 2.0f * (yz + xw);
159    _matrix[10] = 1.0f - 2.0f * ( xx + yy );    rotation[10] = 1.0f - 2.0f * (xx + yy);
160    _matrix[11] = 0;    rotation[11] = 0;
161        
162    /* fourth row */    /* fourth row */
163    _matrix[12] = 0;    rotation[12] = 0;
164    _matrix[13] = 0;    rotation[13] = 0;
165    _matrix[14] = 0;    rotation[14] = 0;
166    _matrix[15] = 1.0f;    rotation[15] = 1.0f;
     
   return _matrix;  
167  }  }
168    
169    
# Line 203  Line 171 
171   * Says if the quaternion in parameter is egal to the current quaternionn, i.e.   * Says if the quaternion in parameter is egal to the current quaternionn, i.e.
172   * the values x, y, z and z are egal.   * the values x, y, z and z are egal.
173   */   */
174  - (BOOL) isEqual: (Quaternion *) quat  - (BOOL) isEqual: (Quaternion *)quat
175  {  {
176    NSParameterAssert (quat);    NSParameterAssert (quat);
177    
# Line 224  Line 192 
192   * t represents the time for the interpolation; it must be valued   * t represents the time for the interpolation; it must be valued
193   * between 0 and 1.   * between 0 and 1.
194   */   */
195  - (void) slerp: (Quaternion *) q1  - (void) slerp: (Quaternion *)q1
196            with: (Quaternion *) q2            with: (Quaternion *)q2
197   accordingTime: (float) t   accordingTime: (float)t
198  {  {
199    NSParameterAssert (q1);    NSParameterAssert (q1);
200    NSParameterAssert (q2);    NSParameterAssert (q2);
# Line 237  Line 205 
205    if ([q1 isEqual: q2])    if ([q1 isEqual: q2])
206      {      {
207        [self initWithValuesX: q1->_x        [self initWithValuesX: q1->_x
208              Y: q1->_y                            Y: q1->_y
209              Z: q1->_z                            Z: q1->_z
210              W: q1->_w];                            W: q1->_w];
211      }      }
     
212    else    else
213      {      {
214        float dotProduct =        float dotProduct =
215          (q1->_x * q2->_x) + (q1->_y * q2->_y) +          q1->_x * q2->_x + q1->_y * q2->_y +
216          (q1->_z * q2->_z) + (q1->_w * q2->_w);          q1->_z * q2->_z + q1->_w * q2->_w;
217        float scale0 = 1 - t, scale1 = t;        float scale0 = 1 - t;
218          float scale1 = t;
219                
220        if (dotProduct < 0.0f) /* angle >= 90° */        if (dotProduct < 0.0f) /* angle >= 90° */
221          {          {
# Line 262  Line 230 
230         */         */
231        if (1 - dotProduct > MIN_VALUE_SPHERICAL_INTERPOLATION)        if (1 - dotProduct > MIN_VALUE_SPHERICAL_INTERPOLATION)
232          {          {
233            float theta = (float) acos (dotProduct);            float theta = (float)acos (dotProduct);
234            float sinTheta = (float) sin (theta);            float sinTheta = (float)sin (theta);
235                        
236            scale0 = (float) sin ((1-t) * theta) / sinTheta;            scale0 = (float)sin ((1-t) * theta) / sinTheta;
237            scale1 = (float) sin (t * theta) / sinTheta;            scale1 = (float)sin (t * theta) / sinTheta;
238          }          }
239                
240        _x = (scale0 * q1->_x) + (scale1 * q2->_x);        _x = scale0 * q1->_x + scale1 * q2->_x;
241        _y = (scale0 * q1->_y) + (scale1 * q2->_y);        _y = scale0 * q1->_y + scale1 * q2->_y;
242        _z = (scale0 * q1->_z) + (scale1 * q2->_z);        _z = scale0 * q1->_z + scale1 * q2->_z;
243        _w = (scale0 * q1->_w) + (scale1 * q2->_w);              _w = scale0 * q1->_w + scale1 * q2->_w;      
244      }      }
245  }  }
246    

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26