|
Blender
V2.59
|
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 }