Blender V2.61 - r43446

editarmature_generate.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: 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 }