2 * $Id: editarmature_generate.c $
4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
28 * editarmature.c: Interface for creating and posing armature objects
34 #include "MEM_guardedalloc.h"
36 #include "DNA_listBase.h"
37 #include "DNA_scene_types.h"
38 #include "DNA_armature_types.h"
40 #include "BLI_blenlib.h"
41 #include "BLI_arithb.h"
42 #include "BLI_graph.h"
44 #include "BKE_utildefines.h"
45 #include "BKE_global.h"
46 #include "BKE_context.h"
48 #include "ED_armature.h"
49 #include "BIF_generate.h"
51 void setBoneRollFromNormal(EditBone *bone, float *no, float invmat[][4], float tmat[][3])
53 if (no != NULL && !VecIsNull(no))
55 float tangent[3], cotangent[3], normal[3];
58 Mat3MulVecfl(tmat, normal);
60 VecSubf(tangent, bone->tail, bone->head);
61 Crossf(cotangent, tangent, normal);
62 Crossf(normal, cotangent, tangent);
66 bone->roll = ED_rollBoneToVector(bone, normal);
70 float calcArcCorrelation(BArcIterator *iter, int start, int end, float v0[3], float n[3])
72 int len = 2 + abs(end - start);
81 /* First pass, calculate average */
82 for (i = start; i <= end; i++)
87 VecSubf(v, iter->p, v0);
92 avg_t += 1.0f; /* adding start (0) and end (1) values */
95 /* Second pass, calculate s_xyz and s_t */
96 for (i = start; i <= end; i++)
102 VecSubf(v, iter->p, v0);
106 dt = VecLength(d) - avg_t;
112 /* adding start(0) and end(1) values to s_t */
113 s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t);
115 return 1.0f - s_xyz / s_t;
123 int nextFixedSubdivision(bContext *C, BArcIterator *iter, int start, int end, float head[3], float p[3])
125 static float stroke_length = 0;
126 static float current_length;
128 Scene *scene = CTX_data_scene(C);
130 float length_threshold;
133 if (stroke_length == 0)
137 IT_peek(iter, start);
140 for (i = start + 1; i <= end; i++)
145 stroke_length += VecLenf(v1, v2);
156 length_threshold = n * stroke_length / scene->toolsettings->skgen_subdivision_number;
158 IT_peek(iter, start);
161 /* < and not <= because we don't care about end, it is P_EXACT anyway */
162 for (i = start + 1; i < end; i++)
167 current_length += VecLenf(v1, v2);
169 if (current_length >= length_threshold)
182 int nextAdaptativeSubdivision(bContext *C, BArcIterator *iter, int start, int end, float head[3], float p[3])
184 Scene *scene = CTX_data_scene(C);
185 float correlation_threshold = scene->toolsettings->skgen_correlation_limit;
190 IT_peek(iter, start);
193 for (i = start + 2; i <= end; i++)
195 /* Calculate normal */
197 VecSubf(n, iter->p, head);
199 if (calcArcCorrelation(iter, start, i, start_p, n) < correlation_threshold)
201 IT_peek(iter, i - 1);
210 int nextLengthSubdivision(bContext *C, BArcIterator *iter, int start, int end, float head[3], float p[3])
212 Scene *scene = CTX_data_scene(C);
213 float lengthLimit = scene->toolsettings->skgen_length_limit;
223 IT_peek(iter, i - 1);
229 /* If lengthLimit hits the current segment */
230 if (VecLenf(vec1, head) > lengthLimit)
237 /* Solve quadratic distance equation */
238 VecSubf(dv, vec1, vec0);
241 VecSubf(off, vec0, head);
242 b = 2 * Inpf(dv, off);
244 c = Inpf(off, off) - (lengthLimit * lengthLimit);
246 f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a);
248 //printf("a %f, b %f, c %f, f %f\n", a, b, c, f);
250 if (isnan(f) == 0 && f < 1.0f)
265 VecSubf(dv, vec1, vec0);
269 VecMulf(p, lengthLimit);
273 return i - 1; /* restart at lower bound */
278 same = 0; // Reset same
285 EditBone * subdivideArcBy(bContext *C, bArmature *arm, ListBase *editbones, BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion)
287 EditBone *lastBone = NULL;
288 EditBone *child = NULL;
289 EditBone *parent = NULL;
291 int end = iter->length;
296 parent = addEditBone(arm, "Bone");
297 VECCOPY(parent->head, iter->p);
299 index = next_subdividion(C, iter, bone_start, end, parent->head, parent->tail);
302 IT_peek(iter, index);
304 child = addEditBone(arm, "Bone");
305 VECCOPY(child->head, parent->tail);
306 child->parent = parent;
307 child->flag |= BONE_CONNECTED;
309 /* going to next bone, fix parent */
310 Mat4MulVecfl(invmat, parent->tail);
311 Mat4MulVecfl(invmat, parent->head);
312 setBoneRollFromNormal(parent, iter->no, invmat, tmat);
314 parent = child; // new child is next parent
315 bone_start = index; // start next bone from current index
317 index = next_subdividion(C, iter, bone_start, end, parent->head, parent->tail);
322 VECCOPY(parent->tail, iter->p);
325 Mat4MulVecfl(invmat, parent->tail);
326 Mat4MulVecfl(invmat, parent->head);
327 setBoneRollFromNormal(parent, iter->no, invmat, tmat);