Blender  V2.59
math_vector.c
Go to the documentation of this file.
00001 /*
00002  * $Id: math_vector.c 35821 2011-03-27 15:54:20Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00021  * All rights reserved.
00022  
00023  * The Original Code is: some of this file.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  * */
00027 
00034 #include "BLI_math.h"
00035 
00036 //******************************* Interpolation *******************************/
00037 
00038 void interp_v2_v2v2(float target[2], const float a[2], const float b[2], const float t)
00039 {
00040         float s = 1.0f-t;
00041 
00042         target[0]= s*a[0] + t*b[0];
00043         target[1]= s*a[1] + t*b[1];
00044 }
00045 
00046 /* weight 3 2D vectors,
00047  * 'w' must be unit length but is not a vector, just 3 weights */
00048 void interp_v2_v2v2v2(float p[2], const float v1[2], const float v2[2], const float v3[2], const float w[3])
00049 {
00050         p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2];
00051         p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2];
00052 }
00053 
00054 void interp_v3_v3v3(float target[3], const float a[3], const float b[3], const float t)
00055 {
00056         float s = 1.0f-t;
00057 
00058         target[0]= s*a[0] + t*b[0];
00059         target[1]= s*a[1] + t*b[1];
00060         target[2]= s*a[2] + t*b[2];
00061 }
00062 
00063 void interp_v4_v4v4(float target[4], const float a[4], const float b[4], const float t)
00064 {
00065         float s = 1.0f-t;
00066 
00067         target[0]= s*a[0] + t*b[0];
00068         target[1]= s*a[1] + t*b[1];
00069         target[2]= s*a[2] + t*b[2];
00070         target[3]= s*a[3] + t*b[3];
00071 }
00072 
00073 /* weight 3 vectors,
00074  * 'w' must be unit length but is not a vector, just 3 weights */
00075 void interp_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3])
00076 {
00077         p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2];
00078         p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2];
00079         p[2] = v1[2]*w[0] + v2[2]*w[1] + v3[2]*w[2];
00080 }
00081 
00082 /* weight 3 vectors,
00083  * 'w' must be unit length but is not a vector, just 4 weights */
00084 void interp_v3_v3v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float w[4])
00085 {
00086         p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2] + v4[0]*w[3];
00087         p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2] + v4[1]*w[3];
00088         p[2] = v1[2]*w[0] + v2[2]*w[1] + v3[2]*w[2] + v4[2]*w[3];
00089 }
00090 
00091 void interp_v4_v4v4v4(float p[4], const float v1[4], const float v2[4], const float v3[4], const float w[3])
00092 {
00093         p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2];
00094         p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2];
00095         p[2] = v1[2]*w[0] + v2[2]*w[1] + v3[2]*w[2];
00096         p[3] = v1[3]*w[0] + v2[3]*w[1] + v3[3]*w[2];
00097 }
00098 
00099 void mid_v3_v3v3(float v[3], const float v1[3], const float v2[3])
00100 {
00101         v[0]= 0.5f*(v1[0] + v2[0]);
00102         v[1]= 0.5f*(v1[1] + v2[1]);
00103         v[2]= 0.5f*(v1[2] + v2[2]);
00104 }
00105 
00106 /********************************** Angles ***********************************/
00107 
00108 /* Return the angle in radians between vecs 1-2 and 2-3 in radians
00109    If v1 is a shoulder, v2 is the elbow and v3 is the hand,
00110    this would return the angle at the elbow */
00111 float angle_v3v3v3(const float v1[3], const float v2[3], const float v3[3])
00112 {
00113         float vec1[3], vec2[3];
00114 
00115         sub_v3_v3v3(vec1, v2, v1);
00116         sub_v3_v3v3(vec2, v2, v3);
00117         normalize_v3(vec1);
00118         normalize_v3(vec2);
00119 
00120         return angle_normalized_v3v3(vec1, vec2);
00121 }
00122 
00123 /* Return the shortest angle in radians between the 2 vectors */
00124 float angle_v3v3(const float v1[3], const float v2[3])
00125 {
00126         float vec1[3], vec2[3];
00127 
00128         normalize_v3_v3(vec1, v1);
00129         normalize_v3_v3(vec2, v2);
00130 
00131         return angle_normalized_v3v3(vec1, vec2);
00132 }
00133 
00134 float angle_v2v2v2(const float v1[2], const float v2[2], const float v3[2])
00135 {
00136         float vec1[2], vec2[2];
00137 
00138         vec1[0] = v2[0]-v1[0];
00139         vec1[1] = v2[1]-v1[1];
00140         
00141         vec2[0] = v2[0]-v3[0];
00142         vec2[1] = v2[1]-v3[1];
00143         
00144         normalize_v2(vec1);
00145         normalize_v2(vec2);
00146 
00147         return angle_normalized_v2v2(vec1, vec2);
00148 }
00149 
00150 /* Return the shortest angle in radians between the 2 vectors */
00151 float angle_v2v2(const float v1[2], const float v2[2])
00152 {
00153         float vec1[2], vec2[2];
00154 
00155         vec1[0] = v1[0];
00156         vec1[1] = v1[1];
00157 
00158         vec2[0] = v2[0];
00159         vec2[1] = v2[1];
00160 
00161         normalize_v2(vec1);
00162         normalize_v2(vec2);
00163 
00164         return angle_normalized_v2v2(vec1, vec2);
00165 }
00166 
00167 float angle_normalized_v3v3(const float v1[3], const float v2[3])
00168 {
00169         /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */
00170         if (dot_v3v3(v1, v2) < 0.0f) {
00171                 float vec[3];
00172                 
00173                 vec[0]= -v2[0];
00174                 vec[1]= -v2[1];
00175                 vec[2]= -v2[2];
00176                 
00177                 return (float)M_PI - 2.0f*(float)saasin(len_v3v3(vec, v1)/2.0f);
00178         }
00179         else
00180                 return 2.0f*(float)saasin(len_v3v3(v2, v1)/2.0f);
00181 }
00182 
00183 float angle_normalized_v2v2(const float v1[2], const float v2[2])
00184 {
00185         /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */
00186         if (dot_v2v2(v1, v2) < 0.0f) {
00187                 float vec[2];
00188                 
00189                 vec[0]= -v2[0];
00190                 vec[1]= -v2[1];
00191                 
00192                 return (float)M_PI - 2.0f*saasin(len_v2v2(vec, v1)/2.0f);
00193         }
00194         else
00195                 return 2.0f*(float)saasin(len_v2v2(v2, v1)/2.0f);
00196 }
00197 
00198 void angle_tri_v3(float angles[3], const float v1[3], const float v2[3], const float v3[3])
00199 {
00200         float ed1[3], ed2[3], ed3[3];
00201 
00202         sub_v3_v3v3(ed1, v3, v1);
00203         sub_v3_v3v3(ed2, v1, v2);
00204         sub_v3_v3v3(ed3, v2, v3);
00205 
00206         normalize_v3(ed1);
00207         normalize_v3(ed2);
00208         normalize_v3(ed3);
00209 
00210         angles[0]= (float)M_PI - angle_normalized_v3v3(ed1, ed2);
00211         angles[1]= (float)M_PI - angle_normalized_v3v3(ed2, ed3);
00212         // face_angles[2] = M_PI - angle_normalized_v3v3(ed3, ed1);
00213         angles[2]= (float)M_PI - (angles[0] + angles[1]);
00214 }
00215 
00216 void angle_quad_v3(float angles[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
00217 {
00218         float ed1[3], ed2[3], ed3[3], ed4[3];
00219 
00220         sub_v3_v3v3(ed1, v4, v1);
00221         sub_v3_v3v3(ed2, v1, v2);
00222         sub_v3_v3v3(ed3, v2, v3);
00223         sub_v3_v3v3(ed4, v3, v4);
00224 
00225         normalize_v3(ed1);
00226         normalize_v3(ed2);
00227         normalize_v3(ed3);
00228         normalize_v3(ed4);
00229 
00230         angles[0]= (float)M_PI - angle_normalized_v3v3(ed1, ed2);
00231         angles[1]= (float)M_PI - angle_normalized_v3v3(ed2, ed3);
00232         angles[2]= (float)M_PI - angle_normalized_v3v3(ed3, ed4);
00233         angles[3]= (float)M_PI - angle_normalized_v3v3(ed4, ed1);
00234 }
00235 
00236 /********************************* Geometry **********************************/
00237 
00238 /* Project v1 on v2 */
00239 void project_v2_v2v2(float c[2], const float v1[2], const float v2[2])
00240 {
00241         float mul;
00242         mul = dot_v2v2(v1, v2) / dot_v2v2(v2, v2);
00243 
00244         c[0] = mul * v2[0];
00245         c[1] = mul * v2[1];
00246 }
00247 
00248 /* Project v1 on v2 */
00249 void project_v3_v3v3(float c[3], const float v1[3], const float v2[3])
00250 {
00251         float mul;
00252         mul = dot_v3v3(v1, v2) / dot_v3v3(v2, v2);
00253         
00254         c[0] = mul * v2[0];
00255         c[1] = mul * v2[1];
00256         c[2] = mul * v2[2];
00257 }
00258 
00259 /* Returns a vector bisecting the angle at v2 formed by v1, v2 and v3 */
00260 void bisect_v3_v3v3v3(float out[3], const float v1[3], const float v2[3], const float v3[3])
00261 {
00262         float d_12[3], d_23[3];
00263         sub_v3_v3v3(d_12, v2, v1);
00264         sub_v3_v3v3(d_23, v3, v2);
00265         normalize_v3(d_12);
00266         normalize_v3(d_23);
00267         add_v3_v3v3(out, d_12, d_23);
00268         normalize_v3(out);
00269 }
00270 
00271 /* Returns a reflection vector from a vector and a normal vector
00272 reflect = vec - ((2 * DotVecs(vec, mirror)) * mirror)
00273 */
00274 void reflect_v3_v3v3(float out[3], const float v1[3], const float v2[3])
00275 {
00276         float vec[3], normal[3];
00277         float reflect[3] = {0.0f, 0.0f, 0.0f};
00278         float dot2;
00279 
00280         copy_v3_v3(vec, v1);
00281         copy_v3_v3(normal, v2);
00282 
00283         dot2 = 2 * dot_v3v3(vec, normal);
00284 
00285         reflect[0] = vec[0] - (dot2 * normal[0]);
00286         reflect[1] = vec[1] - (dot2 * normal[1]);
00287         reflect[2] = vec[2] - (dot2 * normal[2]);
00288 
00289         copy_v3_v3(out, reflect);
00290 }
00291 
00292 void ortho_basis_v3v3_v3(float v1[3], float v2[3], const float v[3])
00293 {
00294         const float f = (float)sqrt(v[0]*v[0] + v[1]*v[1]);
00295 
00296         if (f < 1e-35f) {
00297                 // degenerate case
00298                 v1[0] = (v[2] < 0.0f) ? -1.0f : 1.0f;
00299                 v1[1] = v1[2] = v2[0] = v2[2] = 0.0f;
00300                 v2[1] = 1.0f;
00301         }
00302         else  {
00303                 const float d= 1.0f/f;
00304 
00305                 v1[0] =  v[1]*d;
00306                 v1[1] = -v[0]*d;
00307                 v1[2] = 0.0f;
00308                 v2[0] = -v[2]*v1[1];
00309                 v2[1] = v[2]*v1[0];
00310                 v2[2] = v[0]*v1[1] - v[1]*v1[0];
00311         }
00312 }
00313 
00314 /* Rotate a point p by angle theta around an arbitrary axis r
00315    http://local.wasp.uwa.edu.au/~pbourke/geometry/
00316 */
00317 void rotate_normalized_v3_v3v3fl(float r[3], const float p[3], const float axis[3], const float angle)
00318 {
00319         const float costheta= cos(angle);
00320         const float sintheta= sin(angle);
00321 
00322         r[0]=   ((costheta + (1 - costheta) * axis[0] * axis[0]) * p[0]) +
00323                         (((1 - costheta) * axis[0] * axis[1] - axis[2] * sintheta) * p[1]) +
00324                         (((1 - costheta) * axis[0] * axis[2] + axis[1] * sintheta) * p[2]);
00325 
00326         r[1]=   (((1 - costheta) * axis[0] * axis[1] + axis[2] * sintheta) * p[0]) +
00327                         ((costheta + (1 - costheta) * axis[1] * axis[1]) * p[1]) +
00328                         (((1 - costheta) * axis[1] * axis[2] - axis[0] * sintheta) * p[2]);
00329 
00330         r[2]=   (((1 - costheta) * axis[0] * axis[2] - axis[1] * sintheta) * p[0]) +
00331                         (((1 - costheta) * axis[1] * axis[2] + axis[0] * sintheta) * p[1]) +
00332                         ((costheta + (1 - costheta) * axis[2] * axis[2]) * p[2]);
00333 }
00334 
00335 void rotate_v3_v3v3fl(float r[3], const float p[3], const float axis[3], const float angle)
00336 {
00337         float axis_n[3];
00338 
00339         normalize_v3_v3(axis_n, axis);
00340 
00341         rotate_normalized_v3_v3v3fl(r, p, axis_n, angle);
00342 }
00343 
00344 /*********************************** Other ***********************************/
00345 
00346 void print_v2(const char *str, const float v[2])
00347 {
00348         printf("%s: %.3f %.3f\n", str, v[0], v[1]);
00349 }
00350 
00351 void print_v3(const char *str, const float v[3])
00352 {
00353         printf("%s: %.3f %.3f %.3f\n", str, v[0], v[1], v[2]);
00354 }
00355 
00356 void print_v4(const char *str, const float v[4])
00357 {
00358         printf("%s: %.3f %.3f %.3f %.3f\n", str, v[0], v[1], v[2], v[3]);
00359 }
00360 
00361 void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
00362 {
00363         if(min[0]>vec[0]) min[0]= vec[0];
00364         if(min[1]>vec[1]) min[1]= vec[1];
00365         if(min[2]>vec[2]) min[2]= vec[2];
00366 
00367         if(max[0]<vec[0]) max[0]= vec[0];
00368         if(max[1]<vec[1]) max[1]= vec[1];
00369         if(max[2]<vec[2]) max[2]= vec[2];
00370 }
00371 
00372 
00373 /***************************** Array Functions *******************************/
00374 
00375 void range_vni(int *array_tar, const int size, const int start)
00376 {
00377         int *array_pt= array_tar + (size-1);
00378         int j= start + (size-1);
00379         int i= size;
00380         while(i--) { *(array_pt--) = j--; }
00381 }
00382 
00383 void negate_vn(float *array_tar, const int size)
00384 {
00385         float *array_pt= array_tar + (size-1);
00386         int i= size;
00387         while(i--) { *(array_pt--) *= -1.0f; }
00388 }
00389 
00390 void negate_vn_vn(float *array_tar, const float *array_src, const int size)
00391 {
00392         float *tar= array_tar + (size-1);
00393         const float *src= array_src + (size-1);
00394         int i= size;
00395         while(i--) { *(tar--) = - *(src--); }
00396 }
00397 
00398 void mul_vn_fl(float *array_tar, const int size, const float f)
00399 {
00400         float *array_pt= array_tar + (size-1);
00401         int i= size;
00402         while(i--) { *(array_pt--) *= f; }
00403 }
00404 
00405 void mul_vn_vn_fl(float *array_tar, const float *array_src, const int size, const float f)
00406 {
00407         float *tar= array_tar + (size-1);
00408         const float *src= array_src + (size-1);
00409         int i= size;
00410         while(i--) { *(tar--) = *(src--) * f; }
00411 }
00412 
00413 void add_vn_vn(float *array_tar, const float *array_src, const int size)
00414 {
00415         float *tar= array_tar + (size-1);
00416         const float *src= array_src + (size-1);
00417         int i= size;
00418         while(i--) { *(tar--) += *(src--); }
00419 }
00420 
00421 void add_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size)
00422 {
00423         float *tar= array_tar + (size-1);
00424         const float *src_a= array_src_a + (size-1);
00425         const float *src_b= array_src_b + (size-1);
00426         int i= size;
00427         while(i--) { *(tar--) = *(src_a--) + *(src_b--); }
00428 }
00429 
00430 void sub_vn_vn(float *array_tar, const float *array_src, const int size)
00431 {
00432         float *tar= array_tar + (size-1);
00433         const float *src= array_src + (size-1);
00434         int i= size;
00435         while(i--) { *(tar--) -= *(src--); }
00436 }
00437 
00438 void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size)
00439 {
00440         float *tar= array_tar + (size-1);
00441         const float *src_a= array_src_a + (size-1);
00442         const float *src_b= array_src_b + (size-1);
00443         int i= size;
00444         while(i--) { *(tar--) = *(src_a--) - *(src_b--); }
00445 }
00446 
00447 void fill_vni(int *array_tar, const int size, const int val)
00448 {
00449         int *tar= array_tar + (size-1);
00450         int i= size;
00451         while(i--) { *(tar--) = val; }
00452 }
00453 
00454 void fill_vn(float *array_tar, const int size, const float val)
00455 {
00456         float *tar= array_tar + (size-1);
00457         int i= size;
00458         while(i--) { *(tar--) = val; }
00459 }