Blender V2.61 - r43446

math_vector.c

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