Blender V2.61 - r43446
|
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: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 * editarmature.c: Interface for creating and posing armature objects 00027 */ 00028 00034 #include <string.h> 00035 #include <math.h> 00036 #include <float.h> 00037 00038 00039 #include "DNA_scene_types.h" 00040 #include "DNA_armature_types.h" 00041 00042 #include "BLI_blenlib.h" 00043 #include "BLI_math.h" 00044 #include "BLI_graph.h" 00045 #include "BLI_utildefines.h" 00046 00047 00048 00049 #include "ED_armature.h" 00050 #include "armature_intern.h" 00051 #include "BIF_generate.h" 00052 00053 void setBoneRollFromNormal(EditBone *bone, float *no, float UNUSED(invmat[][4]), float tmat[][3]) 00054 { 00055 if (no != NULL && !is_zero_v3(no)) 00056 { 00057 float normal[3]; 00058 00059 copy_v3_v3(normal, no); 00060 mul_m3_v3(tmat, normal); 00061 00062 bone->roll = ED_rollBoneToVector(bone, normal, FALSE); 00063 } 00064 } 00065 00066 float calcArcCorrelation(BArcIterator *iter, int start, int end, float v0[3], float n[3]) 00067 { 00068 int len = 2 + abs(end - start); 00069 00070 if (len > 2) 00071 { 00072 float avg_t = 0.0f; 00073 float s_t = 0.0f; 00074 float s_xyz = 0.0f; 00075 int i; 00076 00077 /* First pass, calculate average */ 00078 for (i = start; i <= end; i++) 00079 { 00080 float v[3]; 00081 00082 IT_peek(iter, i); 00083 sub_v3_v3v3(v, iter->p, v0); 00084 avg_t += dot_v3v3(v, n); 00085 } 00086 00087 avg_t /= dot_v3v3(n, n); 00088 avg_t += 1.0f; /* adding start (0) and end (1) values */ 00089 avg_t /= len; 00090 00091 /* Second pass, calculate s_xyz and s_t */ 00092 for (i = start; i <= end; i++) 00093 { 00094 float v[3], d[3]; 00095 float dt; 00096 00097 IT_peek(iter, i); 00098 sub_v3_v3v3(v, iter->p, v0); 00099 project_v3_v3v3(d, v, n); 00100 sub_v3_v3(v, d); 00101 00102 dt = len_v3(d) - avg_t; 00103 00104 s_t += dt * dt; 00105 s_xyz += dot_v3v3(v, v); 00106 } 00107 00108 /* adding start(0) and end(1) values to s_t */ 00109 s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t); 00110 00111 return 1.0f - s_xyz / s_t; 00112 } 00113 else 00114 { 00115 return 1.0f; 00116 } 00117 } 00118 00119 int nextFixedSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float UNUSED(head[3]), float p[3]) 00120 { 00121 static float stroke_length = 0; 00122 static float current_length; 00123 static char n; 00124 float *v1, *v2; 00125 float length_threshold; 00126 int i; 00127 00128 if (stroke_length == 0) 00129 { 00130 current_length = 0; 00131 00132 IT_peek(iter, start); 00133 v1 = iter->p; 00134 00135 for (i = start + 1; i <= end; i++) 00136 { 00137 IT_peek(iter, i); 00138 v2 = iter->p; 00139 00140 stroke_length += len_v3v3(v1, v2); 00141 00142 v1 = v2; 00143 } 00144 00145 n = 0; 00146 current_length = 0; 00147 } 00148 00149 n++; 00150 00151 length_threshold = n * stroke_length / toolsettings->skgen_subdivision_number; 00152 00153 IT_peek(iter, start); 00154 v1 = iter->p; 00155 00156 /* < and not <= because we don't care about end, it is P_EXACT anyway */ 00157 for (i = start + 1; i < end; i++) 00158 { 00159 IT_peek(iter, i); 00160 v2 = iter->p; 00161 00162 current_length += len_v3v3(v1, v2); 00163 00164 if (current_length >= length_threshold) 00165 { 00166 VECCOPY(p, v2); 00167 return i; 00168 } 00169 00170 v1 = v2; 00171 } 00172 00173 stroke_length = 0; 00174 00175 return -1; 00176 } 00177 int nextAdaptativeSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float head[3], float p[3]) 00178 { 00179 float correlation_threshold = toolsettings->skgen_correlation_limit; 00180 float *start_p; 00181 float n[3]; 00182 int i; 00183 00184 IT_peek(iter, start); 00185 start_p = iter->p; 00186 00187 for (i = start + 2; i <= end; i++) 00188 { 00189 /* Calculate normal */ 00190 IT_peek(iter, i); 00191 sub_v3_v3v3(n, iter->p, head); 00192 00193 if (calcArcCorrelation(iter, start, i, start_p, n) < correlation_threshold) 00194 { 00195 IT_peek(iter, i - 1); 00196 VECCOPY(p, iter->p); 00197 return i - 1; 00198 } 00199 } 00200 00201 return -1; 00202 } 00203 00204 int nextLengthSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float head[3], float p[3]) 00205 { 00206 float lengthLimit = toolsettings->skgen_length_limit; 00207 int same = 1; 00208 int i; 00209 00210 i = start + 1; 00211 while (i <= end) 00212 { 00213 float *vec0; 00214 float *vec1; 00215 00216 IT_peek(iter, i - 1); 00217 vec0 = iter->p; 00218 00219 IT_peek(iter, i); 00220 vec1 = iter->p; 00221 00222 /* If lengthLimit hits the current segment */ 00223 if (len_v3v3(vec1, head) > lengthLimit) 00224 { 00225 if (same == 0) 00226 { 00227 float dv[3], off[3]; 00228 float a, b, c, f; 00229 00230 /* Solve quadratic distance equation */ 00231 sub_v3_v3v3(dv, vec1, vec0); 00232 a = dot_v3v3(dv, dv); 00233 00234 sub_v3_v3v3(off, vec0, head); 00235 b = 2 * dot_v3v3(dv, off); 00236 00237 c = dot_v3v3(off, off) - (lengthLimit * lengthLimit); 00238 00239 f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a); 00240 00241 //printf("a %f, b %f, c %f, f %f\n", a, b, c, f); 00242 00243 if (isnan(f) == 0 && f < 1.0f) 00244 { 00245 VECCOPY(p, dv); 00246 mul_v3_fl(p, f); 00247 add_v3_v3(p, vec0); 00248 } 00249 else 00250 { 00251 VECCOPY(p, vec1); 00252 } 00253 } 00254 else 00255 { 00256 float dv[3]; 00257 00258 sub_v3_v3v3(dv, vec1, vec0); 00259 normalize_v3(dv); 00260 00261 VECCOPY(p, dv); 00262 mul_v3_fl(p, lengthLimit); 00263 add_v3_v3(p, head); 00264 } 00265 00266 return i - 1; /* restart at lower bound */ 00267 } 00268 else 00269 { 00270 i++; 00271 same = 0; // Reset same 00272 } 00273 } 00274 00275 return -1; 00276 } 00277 00278 EditBone * subdivideArcBy(ToolSettings *toolsettings, bArmature *arm, ListBase *UNUSED(editbones), BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion) 00279 { 00280 EditBone *lastBone = NULL; 00281 EditBone *child = NULL; 00282 EditBone *parent = NULL; 00283 float *normal = NULL; 00284 float size_buffer = 1.2; 00285 int bone_start = 0; 00286 int end = iter->length; 00287 int index; 00288 00289 IT_head(iter); 00290 00291 parent = ED_armature_edit_bone_add(arm, "Bone"); 00292 VECCOPY(parent->head, iter->p); 00293 00294 if (iter->size > 0) 00295 { 00296 parent->rad_head = iter->size * size_buffer; 00297 } 00298 00299 normal = iter->no; 00300 00301 index = next_subdividion(toolsettings, iter, bone_start, end, parent->head, parent->tail); 00302 while (index != -1) 00303 { 00304 IT_peek(iter, index); 00305 00306 child = ED_armature_edit_bone_add(arm, "Bone"); 00307 VECCOPY(child->head, parent->tail); 00308 child->parent = parent; 00309 child->flag |= BONE_CONNECTED; 00310 00311 if (iter->size > 0) 00312 { 00313 child->rad_head = iter->size * size_buffer; 00314 parent->rad_tail = iter->size * size_buffer; 00315 } 00316 00317 /* going to next bone, fix parent */ 00318 mul_m4_v3(invmat, parent->tail); 00319 mul_m4_v3(invmat, parent->head); 00320 setBoneRollFromNormal(parent, normal, invmat, tmat); 00321 00322 parent = child; // new child is next parent 00323 bone_start = index; // start next bone from current index 00324 00325 normal = iter->no; /* use normal at head, not tail */ 00326 00327 index = next_subdividion(toolsettings, iter, bone_start, end, parent->head, parent->tail); 00328 } 00329 00330 iter->tail(iter); 00331 00332 VECCOPY(parent->tail, iter->p); 00333 if (iter->size > 0) 00334 { 00335 parent->rad_tail = iter->size * size_buffer; 00336 } 00337 00338 /* fix last bone */ 00339 mul_m4_v3(invmat, parent->tail); 00340 mul_m4_v3(invmat, parent->head); 00341 setBoneRollFromNormal(parent, iter->no, invmat, tmat); 00342 lastBone = parent; 00343 00344 return lastBone; 00345 }