Blender  V2.59
editarmature_generate.c
Go to the documentation of this file.
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 }