bugfix [#24907] bone roll z up broken and python script showing correct method to...
[blender.git] / source / blender / editors / armature / editarmature_generate.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
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.
10  *
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.
15  *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * editarmature.c: Interface for creating and posing armature objects
29  */
30
31 #include <string.h>
32 #include <math.h>
33 #include <float.h>
34
35
36 #include "DNA_scene_types.h"
37 #include "DNA_armature_types.h"
38
39 #include "BLI_blenlib.h"
40 #include "BLI_math.h"
41 #include "BLI_graph.h"
42  
43 #include "BKE_utildefines.h"
44
45 #include "ED_armature.h"
46 #include "armature_intern.h"
47 #include "BIF_generate.h"
48
49 void setBoneRollFromNormal(EditBone *bone, float *no, float UNUSED(invmat[][4]), float tmat[][3])
50 {
51         if (no != NULL && !is_zero_v3(no))
52         {
53                 float normal[3];
54
55                 copy_v3_v3(normal, no); 
56                 mul_m3_v3(tmat, normal);
57                 
58                 bone->roll = ED_rollBoneToVector(bone, normal, FALSE);
59         }
60 }
61
62 float calcArcCorrelation(BArcIterator *iter, int start, int end, float v0[3], float n[3])
63 {
64         int len = 2 + abs(end - start);
65         
66         if (len > 2)
67         {
68                 float avg_t = 0.0f;
69                 float s_t = 0.0f;
70                 float s_xyz = 0.0f;
71                 int i;
72                 
73                 /* First pass, calculate average */
74                 for (i = start; i <= end; i++)
75                 {
76                         float v[3];
77                         
78                         IT_peek(iter, i);
79                         sub_v3_v3v3(v, iter->p, v0);
80                         avg_t += dot_v3v3(v, n);
81                 }
82                 
83                 avg_t /= dot_v3v3(n, n);
84                 avg_t += 1.0f; /* adding start (0) and end (1) values */
85                 avg_t /= len;
86                 
87                 /* Second pass, calculate s_xyz and s_t */
88                 for (i = start; i <= end; i++)
89                 {
90                         float v[3], d[3];
91                         float dt;
92                         
93                         IT_peek(iter, i);
94                         sub_v3_v3v3(v, iter->p, v0);
95                         project_v3_v3v3(d, v, n);
96                         sub_v3_v3(v, d);
97                         
98                         dt = len_v3(d) - avg_t;
99                         
100                         s_t += dt * dt;
101                         s_xyz += dot_v3v3(v, v);
102                 }
103                 
104                 /* adding start(0) and end(1) values to s_t */
105                 s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t);
106                 
107                 return 1.0f - s_xyz / s_t; 
108         }
109         else
110         {
111                 return 1.0f;
112         }
113 }
114
115 int nextFixedSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float UNUSED(head[3]), float p[3])
116 {
117         static float stroke_length = 0;
118         static float current_length;
119         static char n;
120         float *v1, *v2;
121         float length_threshold;
122         int i;
123         
124         if (stroke_length == 0)
125         {
126                 current_length = 0;
127
128                 IT_peek(iter, start);
129                 v1 = iter->p;
130                 
131                 for (i = start + 1; i <= end; i++)
132                 {
133                         IT_peek(iter, i);
134                         v2 = iter->p;
135
136                         stroke_length += len_v3v3(v1, v2);
137                         
138                         v1 = v2;
139                 }
140                 
141                 n = 0;
142                 current_length = 0;
143         }
144         
145         n++;
146         
147         length_threshold = n * stroke_length / toolsettings->skgen_subdivision_number;
148         
149         IT_peek(iter, start);
150         v1 = iter->p;
151
152         /* < and not <= because we don't care about end, it is P_EXACT anyway */
153         for (i = start + 1; i < end; i++)
154         {
155                 IT_peek(iter, i);
156                 v2 = iter->p;
157
158                 current_length += len_v3v3(v1, v2);
159
160                 if (current_length >= length_threshold)
161                 {
162                         VECCOPY(p, v2);
163                         return i;
164                 }
165                 
166                 v1 = v2;
167         }
168         
169         stroke_length = 0;
170         
171         return -1;
172 }
173 int nextAdaptativeSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float head[3], float p[3])
174 {
175         float correlation_threshold = toolsettings->skgen_correlation_limit;
176         float *start_p;
177         float n[3];
178         int i;
179         
180         IT_peek(iter, start);
181         start_p = iter->p;
182
183         for (i = start + 2; i <= end; i++)
184         {
185                 /* Calculate normal */
186                 IT_peek(iter, i);
187                 sub_v3_v3v3(n, iter->p, head);
188
189                 if (calcArcCorrelation(iter, start, i, start_p, n) < correlation_threshold)
190                 {
191                         IT_peek(iter, i - 1);
192                         VECCOPY(p, iter->p);
193                         return i - 1;
194                 }
195         }
196         
197         return -1;
198 }
199
200 int nextLengthSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float head[3], float p[3])
201 {
202         float lengthLimit = toolsettings->skgen_length_limit;
203         int same = 1;
204         int i;
205         
206         i = start + 1;
207         while (i <= end)
208         {
209                 float *vec0;
210                 float *vec1;
211                 
212                 IT_peek(iter, i - 1);
213                 vec0 = iter->p;
214
215                 IT_peek(iter, i);
216                 vec1 = iter->p;
217                 
218                 /* If lengthLimit hits the current segment */
219                 if (len_v3v3(vec1, head) > lengthLimit)
220                 {
221                         if (same == 0)
222                         {
223                                 float dv[3], off[3];
224                                 float a, b, c, f;
225                                 
226                                 /* Solve quadratic distance equation */
227                                 sub_v3_v3v3(dv, vec1, vec0);
228                                 a = dot_v3v3(dv, dv);
229                                 
230                                 sub_v3_v3v3(off, vec0, head);
231                                 b = 2 * dot_v3v3(dv, off);
232                                 
233                                 c = dot_v3v3(off, off) - (lengthLimit * lengthLimit);
234                                 
235                                 f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a);
236                                 
237                                 //printf("a %f, b %f, c %f, f %f\n", a, b, c, f);
238                                 
239                                 if (isnan(f) == 0 && f < 1.0f)
240                                 {
241                                         VECCOPY(p, dv);
242                                         mul_v3_fl(p, f);
243                                         add_v3_v3(p, vec0);
244                                 }
245                                 else
246                                 {
247                                         VECCOPY(p, vec1);
248                                 }
249                         }
250                         else
251                         {
252                                 float dv[3];
253                                 
254                                 sub_v3_v3v3(dv, vec1, vec0);
255                                 normalize_v3(dv);
256                                  
257                                 VECCOPY(p, dv);
258                                 mul_v3_fl(p, lengthLimit);
259                                 add_v3_v3(p, head);
260                         }
261                         
262                         return i - 1; /* restart at lower bound */
263                 }
264                 else
265                 {
266                         i++;
267                         same = 0; // Reset same
268                 }
269         }
270         
271         return -1;
272 }
273
274 EditBone * subdivideArcBy(ToolSettings *toolsettings, bArmature *arm, ListBase *UNUSED(editbones), BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion)
275 {
276         EditBone *lastBone = NULL;
277         EditBone *child = NULL;
278         EditBone *parent = NULL;
279         float *normal = NULL;
280         float size_buffer = 1.2;
281         int bone_start = 0;
282         int end = iter->length;
283         int index;
284         
285         IT_head(iter);
286         
287         parent = ED_armature_edit_bone_add(arm, "Bone");
288         VECCOPY(parent->head, iter->p);
289         
290         if (iter->size > 0)
291         {
292                 parent->rad_head = iter->size * size_buffer;
293         }
294         
295         normal = iter->no;
296         
297         index = next_subdividion(toolsettings, iter, bone_start, end, parent->head, parent->tail);
298         while (index != -1)
299         {
300                 IT_peek(iter, index);
301
302                 child = ED_armature_edit_bone_add(arm, "Bone");
303                 VECCOPY(child->head, parent->tail);
304                 child->parent = parent;
305                 child->flag |= BONE_CONNECTED;
306                 
307                 if (iter->size > 0)
308                 {
309                         child->rad_head = iter->size * size_buffer;
310                         parent->rad_tail = iter->size * size_buffer;
311                 }
312
313                 /* going to next bone, fix parent */
314                 mul_m4_v3(invmat, parent->tail);
315                 mul_m4_v3(invmat, parent->head);
316                 setBoneRollFromNormal(parent, normal, invmat, tmat);
317
318                 parent = child; // new child is next parent
319                 bone_start = index; // start next bone from current index
320
321                 normal = iter->no; /* use normal at head, not tail */
322
323                 index = next_subdividion(toolsettings, iter, bone_start, end, parent->head, parent->tail);
324         }
325         
326         iter->tail(iter);
327
328         VECCOPY(parent->tail, iter->p);
329         if (iter->size > 0)
330         {
331                 parent->rad_tail = iter->size * size_buffer;
332         }
333                 
334         /* fix last bone */
335         mul_m4_v3(invmat, parent->tail);
336         mul_m4_v3(invmat, parent->head);
337         setBoneRollFromNormal(parent, iter->no, invmat, tmat);
338         lastBone = parent;
339         
340         return lastBone;
341 }