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