svn merge -r 21041:21301 https://svn.blender.org/svnroot/bf-blender/branches/blender2...
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_listBase.h"
37 #include "DNA_scene_types.h"
38 #include "DNA_armature_types.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_arithb.h"
42 #include "BLI_graph.h"
43  
44 #include "BKE_utildefines.h"
45 #include "BKE_global.h"
46 #include "BKE_context.h"
47
48 #include "ED_armature.h"
49 #include "armature_intern.h"
50 #include "BIF_generate.h"
51
52 void setBoneRollFromNormal(EditBone *bone, float *no, float invmat[][4], float tmat[][3])
53 {
54         if (no != NULL && !VecIsNull(no))
55         {
56                 float tangent[3], vec[3], normal[3];
57
58                 VECCOPY(normal, no);    
59                 Mat3MulVecfl(tmat, normal);
60
61                 VecSubf(tangent, bone->tail, bone->head);
62                 Projf(vec, tangent, normal);
63                 VecSubf(normal, normal, vec);
64                 
65                 Normalize(normal);
66                 
67                 bone->roll = ED_rollBoneToVector(bone, normal);
68         }
69 }
70
71 float calcArcCorrelation(BArcIterator *iter, int start, int end, float v0[3], float n[3])
72 {
73         int len = 2 + abs(end - start);
74         
75         if (len > 2)
76         {
77                 float avg_t = 0.0f;
78                 float s_t = 0.0f;
79                 float s_xyz = 0.0f;
80                 int i;
81                 
82                 /* First pass, calculate average */
83                 for (i = start; i <= end; i++)
84                 {
85                         float v[3];
86                         
87                         IT_peek(iter, i);
88                         VecSubf(v, iter->p, v0);
89                         avg_t += Inpf(v, n);
90                 }
91                 
92                 avg_t /= Inpf(n, n);
93                 avg_t += 1.0f; /* adding start (0) and end (1) values */
94                 avg_t /= len;
95                 
96                 /* Second pass, calculate s_xyz and s_t */
97                 for (i = start; i <= end; i++)
98                 {
99                         float v[3], d[3];
100                         float dt;
101                         
102                         IT_peek(iter, i);
103                         VecSubf(v, iter->p, v0);
104                         Projf(d, v, n);
105                         VecSubf(v, v, d);
106                         
107                         dt = VecLength(d) - avg_t;
108                         
109                         s_t += dt * dt;
110                         s_xyz += Inpf(v, v);
111                 }
112                 
113                 /* adding start(0) and end(1) values to s_t */
114                 s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t);
115                 
116                 return 1.0f - s_xyz / s_t; 
117         }
118         else
119         {
120                 return 1.0f;
121         }
122 }
123
124 int nextFixedSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float head[3], float p[3])
125 {
126         static float stroke_length = 0;
127         static float current_length;
128         static char n;
129         float *v1, *v2;
130         float length_threshold;
131         int i;
132         
133         if (stroke_length == 0)
134         {
135                 current_length = 0;
136
137                 IT_peek(iter, start);
138                 v1 = iter->p;
139                 
140                 for (i = start + 1; i <= end; i++)
141                 {
142                         IT_peek(iter, i);
143                         v2 = iter->p;
144
145                         stroke_length += VecLenf(v1, v2);
146                         
147                         v1 = v2;
148                 }
149                 
150                 n = 0;
151                 current_length = 0;
152         }
153         
154         n++;
155         
156         length_threshold = n * stroke_length / toolsettings->skgen_subdivision_number;
157         
158         IT_peek(iter, start);
159         v1 = iter->p;
160
161         /* < and not <= because we don't care about end, it is P_EXACT anyway */
162         for (i = start + 1; i < end; i++)
163         {
164                 IT_peek(iter, i);
165                 v2 = iter->p;
166
167                 current_length += VecLenf(v1, v2);
168
169                 if (current_length >= length_threshold)
170                 {
171                         VECCOPY(p, v2);
172                         return i;
173                 }
174                 
175                 v1 = v2;
176         }
177         
178         stroke_length = 0;
179         
180         return -1;
181 }
182 int nextAdaptativeSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float head[3], float p[3])
183 {
184         float correlation_threshold = toolsettings->skgen_correlation_limit;
185         float *start_p;
186         float n[3];
187         int i;
188         
189         IT_peek(iter, start);
190         start_p = iter->p;
191
192         for (i = start + 2; i <= end; i++)
193         {
194                 /* Calculate normal */
195                 IT_peek(iter, i);
196                 VecSubf(n, iter->p, head);
197
198                 if (calcArcCorrelation(iter, start, i, start_p, n) < correlation_threshold)
199                 {
200                         IT_peek(iter, i - 1);
201                         VECCOPY(p, iter->p);
202                         return i - 1;
203                 }
204         }
205         
206         return -1;
207 }
208
209 int nextLengthSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float head[3], float p[3])
210 {
211         float lengthLimit = toolsettings->skgen_length_limit;
212         int same = 1;
213         int i;
214         
215         i = start + 1;
216         while (i <= end)
217         {
218                 float *vec0;
219                 float *vec1;
220                 
221                 IT_peek(iter, i - 1);
222                 vec0 = iter->p;
223
224                 IT_peek(iter, i);
225                 vec1 = iter->p;
226                 
227                 /* If lengthLimit hits the current segment */
228                 if (VecLenf(vec1, head) > lengthLimit)
229                 {
230                         if (same == 0)
231                         {
232                                 float dv[3], off[3];
233                                 float a, b, c, f;
234                                 
235                                 /* Solve quadratic distance equation */
236                                 VecSubf(dv, vec1, vec0);
237                                 a = Inpf(dv, dv);
238                                 
239                                 VecSubf(off, vec0, head);
240                                 b = 2 * Inpf(dv, off);
241                                 
242                                 c = Inpf(off, off) - (lengthLimit * lengthLimit);
243                                 
244                                 f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a);
245                                 
246                                 //printf("a %f, b %f, c %f, f %f\n", a, b, c, f);
247                                 
248                                 if (isnan(f) == 0 && f < 1.0f)
249                                 {
250                                         VECCOPY(p, dv);
251                                         VecMulf(p, f);
252                                         VecAddf(p, p, vec0);
253                                 }
254                                 else
255                                 {
256                                         VECCOPY(p, vec1);
257                                 }
258                         }
259                         else
260                         {
261                                 float dv[3];
262                                 
263                                 VecSubf(dv, vec1, vec0);
264                                 Normalize(dv);
265                                  
266                                 VECCOPY(p, dv);
267                                 VecMulf(p, lengthLimit);
268                                 VecAddf(p, p, head);
269                         }
270                         
271                         return i - 1; /* restart at lower bound */
272                 }
273                 else
274                 {
275                         i++;
276                         same = 0; // Reset same
277                 }
278         }
279         
280         return -1;
281 }
282
283 EditBone * subdivideArcBy(ToolSettings *toolsettings, bArmature *arm, ListBase *editbones, BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion)
284 {
285         EditBone *lastBone = NULL;
286         EditBone *child = NULL;
287         EditBone *parent = NULL;
288         int bone_start = 0;
289         int end = iter->length;
290         int index;
291         
292         IT_head(iter);
293         
294         parent = addEditBone(arm, "Bone");
295         VECCOPY(parent->head, iter->p);
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 = addEditBone(arm, "Bone");
303                 VECCOPY(child->head, parent->tail);
304                 child->parent = parent;
305                 child->flag |= BONE_CONNECTED;
306                 
307                 /* going to next bone, fix parent */
308                 Mat4MulVecfl(invmat, parent->tail);
309                 Mat4MulVecfl(invmat, parent->head);
310                 setBoneRollFromNormal(parent, iter->no, invmat, tmat);
311
312                 parent = child; // new child is next parent
313                 bone_start = index; // start next bone from current index
314
315                 index = next_subdividion(toolsettings, iter, bone_start, end, parent->head, parent->tail);
316         }
317         
318         iter->tail(iter);
319
320         VECCOPY(parent->tail, iter->p);
321
322         /* fix last bone */
323         Mat4MulVecfl(invmat, parent->tail);
324         Mat4MulVecfl(invmat, parent->head);
325         setBoneRollFromNormal(parent, iter->no, invmat, tmat);
326         lastBone = parent;
327         
328         return lastBone;
329 }