Blender V2.61 - r43446
|
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 * Contributor(s): none yet. 00019 * 00020 * ***** END GPL LICENSE BLOCK ***** 00021 */ 00022 00028 #include <string.h> 00029 #include <math.h> 00030 #include <float.h> 00031 00032 #include "MEM_guardedalloc.h" 00033 00034 #include "BLI_blenlib.h" 00035 #include "BLI_math.h" 00036 #include "BLI_utildefines.h" 00037 00038 #include "BKE_sketch.h" 00039 00040 00041 #include "DNA_userdef_types.h" 00042 00043 void freeSketch(SK_Sketch *sketch) 00044 { 00045 SK_Stroke *stk, *next; 00046 00047 for (stk = sketch->strokes.first; stk; stk = next) 00048 { 00049 next = stk->next; 00050 00051 sk_freeStroke(stk); 00052 } 00053 00054 BLI_freelistN(&sketch->depth_peels); 00055 00056 MEM_freeN(sketch); 00057 } 00058 00059 SK_Sketch* createSketch(void) 00060 { 00061 SK_Sketch *sketch; 00062 00063 sketch = MEM_callocN(sizeof(SK_Sketch), "SK_Sketch"); 00064 00065 sketch->active_stroke = NULL; 00066 sketch->gesture = NULL; 00067 00068 sketch->strokes.first = NULL; 00069 sketch->strokes.last = NULL; 00070 00071 return sketch; 00072 } 00073 00074 void sk_initPoint(SK_Point *pt, SK_DrawData *dd, float *no) 00075 { 00076 if (no) 00077 { 00078 normalize_v3_v3(pt->no, no); 00079 } 00080 else 00081 { 00082 pt->no[0] = 0; 00083 pt->no[1] = 0; 00084 pt->no[2] = 1; 00085 } 00086 pt->p2d[0] = dd->mval[0]; 00087 pt->p2d[1] = dd->mval[1]; 00088 /* more init code here */ 00089 } 00090 00091 void sk_copyPoint(SK_Point *dst, SK_Point *src) 00092 { 00093 memcpy(dst, src, sizeof(SK_Point)); 00094 } 00095 00096 void sk_allocStrokeBuffer(SK_Stroke *stk) 00097 { 00098 stk->points = MEM_callocN(sizeof(SK_Point) * stk->buf_size, "SK_Point buffer"); 00099 } 00100 00101 void sk_freeStroke(SK_Stroke *stk) 00102 { 00103 MEM_freeN(stk->points); 00104 MEM_freeN(stk); 00105 } 00106 00107 SK_Stroke* sk_createStroke(void) 00108 { 00109 SK_Stroke *stk; 00110 00111 stk = MEM_callocN(sizeof(SK_Stroke), "SK_Stroke"); 00112 00113 stk->selected = 0; 00114 stk->nb_points = 0; 00115 stk->buf_size = SK_Stroke_BUFFER_INIT_SIZE; 00116 00117 sk_allocStrokeBuffer(stk); 00118 00119 return stk; 00120 } 00121 00122 void sk_shrinkStrokeBuffer(SK_Stroke *stk) 00123 { 00124 if (stk->nb_points < stk->buf_size) 00125 { 00126 SK_Point *old_points = stk->points; 00127 00128 stk->buf_size = stk->nb_points; 00129 00130 sk_allocStrokeBuffer(stk); 00131 00132 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points); 00133 00134 MEM_freeN(old_points); 00135 } 00136 } 00137 00138 void sk_growStrokeBuffer(SK_Stroke *stk) 00139 { 00140 if (stk->nb_points == stk->buf_size) 00141 { 00142 SK_Point *old_points = stk->points; 00143 00144 stk->buf_size *= 2; 00145 00146 sk_allocStrokeBuffer(stk); 00147 00148 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points); 00149 00150 MEM_freeN(old_points); 00151 } 00152 } 00153 00154 void sk_growStrokeBufferN(SK_Stroke *stk, int n) 00155 { 00156 if (stk->nb_points + n > stk->buf_size) 00157 { 00158 SK_Point *old_points = stk->points; 00159 00160 while (stk->nb_points + n > stk->buf_size) 00161 { 00162 stk->buf_size *= 2; 00163 } 00164 00165 sk_allocStrokeBuffer(stk); 00166 00167 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points); 00168 00169 MEM_freeN(old_points); 00170 } 00171 } 00172 00173 00174 void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n) 00175 { 00176 memcpy(stk->points + n, pt, sizeof(SK_Point)); 00177 } 00178 00179 void sk_insertStrokePoint(SK_Stroke *stk, SK_Point *pt, int n) 00180 { 00181 int size = stk->nb_points - n; 00182 00183 sk_growStrokeBuffer(stk); 00184 00185 memmove(stk->points + n + 1, stk->points + n, size * sizeof(SK_Point)); 00186 00187 memcpy(stk->points + n, pt, sizeof(SK_Point)); 00188 00189 stk->nb_points++; 00190 } 00191 00192 void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt) 00193 { 00194 sk_growStrokeBuffer(stk); 00195 00196 memcpy(stk->points + stk->nb_points, pt, sizeof(SK_Point)); 00197 00198 stk->nb_points++; 00199 } 00200 00201 void sk_insertStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end) 00202 { 00203 int size = end - start + 1; 00204 00205 sk_growStrokeBufferN(stk, len - size); 00206 00207 if (len != size) 00208 { 00209 int tail_size = stk->nb_points - end + 1; 00210 00211 memmove(stk->points + start + len, stk->points + end + 1, tail_size * sizeof(SK_Point)); 00212 } 00213 00214 memcpy(stk->points + start, pts, len * sizeof(SK_Point)); 00215 00216 stk->nb_points += len - size; 00217 } 00218 00219 void sk_trimStroke(SK_Stroke *stk, int start, int end) 00220 { 00221 int size = end - start + 1; 00222 00223 if (start > 0) 00224 { 00225 memmove(stk->points, stk->points + start, size * sizeof(SK_Point)); 00226 } 00227 00228 stk->nb_points = size; 00229 } 00230 00231 void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3]) 00232 { 00233 SK_Point pt1, pt2; 00234 SK_Point *prev, *next; 00235 float delta_p[3]; 00236 int i, total; 00237 00238 total = end - start; 00239 00240 sub_v3_v3v3(delta_p, p_end, p_start); 00241 00242 prev = stk->points + start; 00243 next = stk->points + end; 00244 00245 copy_v3_v3(pt1.p, p_start); 00246 copy_v3_v3(pt1.no, prev->no); 00247 pt1.mode = prev->mode; 00248 pt1.type = prev->type; 00249 00250 copy_v3_v3(pt2.p, p_end); 00251 copy_v3_v3(pt2.no, next->no); 00252 pt2.mode = next->mode; 00253 pt2.type = next->type; 00254 00255 sk_insertStrokePoint(stk, &pt1, start + 1); /* insert after start */ 00256 sk_insertStrokePoint(stk, &pt2, end + 1); /* insert before end (since end was pushed back already) */ 00257 00258 for (i = 1; i < total; i++) 00259 { 00260 float delta = (float)i / (float)total; 00261 float *p = stk->points[start + 1 + i].p; 00262 00263 VECCOPY(p, delta_p); 00264 mul_v3_fl(p, delta); 00265 add_v3_v3(p, p_start); 00266 } 00267 } 00268 00269 void sk_polygonizeStroke(SK_Stroke *stk, int start, int end) 00270 { 00271 int offset; 00272 int i; 00273 00274 /* find first exact points outside of range */ 00275 for (;start > 0; start--) 00276 { 00277 if (stk->points[start].type == PT_EXACT) 00278 { 00279 break; 00280 } 00281 } 00282 00283 for (;end < stk->nb_points - 1; end++) 00284 { 00285 if (stk->points[end].type == PT_EXACT) 00286 { 00287 break; 00288 } 00289 } 00290 00291 offset = start + 1; 00292 00293 for (i = start + 1; i < end; i++) 00294 { 00295 if (stk->points[i].type == PT_EXACT) 00296 { 00297 if (offset != i) 00298 { 00299 memcpy(stk->points + offset, stk->points + i, sizeof(SK_Point)); 00300 } 00301 00302 offset++; 00303 } 00304 } 00305 00306 /* some points were removes, move end of array */ 00307 if (offset < end) 00308 { 00309 int size = stk->nb_points - end; 00310 memmove(stk->points + offset, stk->points + end, size * sizeof(SK_Point)); 00311 stk->nb_points = offset + size; 00312 } 00313 } 00314 00315 void sk_flattenStroke(SK_Stroke *stk, int start, int end) 00316 { 00317 float normal[3], distance[3]; 00318 float limit; 00319 int i, total; 00320 00321 total = end - start + 1; 00322 00323 copy_v3_v3(normal, stk->points[start].no); 00324 00325 sub_v3_v3v3(distance, stk->points[end].p, stk->points[start].p); 00326 project_v3_v3v3(normal, distance, normal); 00327 limit = normalize_v3(normal); 00328 00329 for (i = 1; i < total - 1; i++) 00330 { 00331 float d = limit * i / total; 00332 float offset[3]; 00333 float *p = stk->points[start + i].p; 00334 00335 sub_v3_v3v3(distance, p, stk->points[start].p); 00336 project_v3_v3v3(distance, distance, normal); 00337 00338 VECCOPY(offset, normal); 00339 mul_v3_fl(offset, d); 00340 00341 sub_v3_v3(p, distance); 00342 add_v3_v3(p, offset); 00343 } 00344 } 00345 00346 void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk) 00347 { 00348 if (sketch->active_stroke == stk) 00349 { 00350 sketch->active_stroke = NULL; 00351 } 00352 00353 BLI_remlink(&sketch->strokes, stk); 00354 sk_freeStroke(stk); 00355 } 00356 00357 void sk_reverseStroke(SK_Stroke *stk) 00358 { 00359 SK_Point *old_points = stk->points; 00360 int i = 0; 00361 00362 sk_allocStrokeBuffer(stk); 00363 00364 for (i = 0; i < stk->nb_points; i++) 00365 { 00366 sk_copyPoint(stk->points + i, old_points + stk->nb_points - 1 - i); 00367 } 00368 00369 MEM_freeN(old_points); 00370 } 00371 00372 00373 /* Ramer-Douglas-Peucker algorithm for line simplification */ 00374 void sk_filterStroke(SK_Stroke *stk, int start, int end) 00375 { 00376 SK_Point *old_points = stk->points; 00377 int nb_points = stk->nb_points; 00378 char *marked = NULL; 00379 char work; 00380 int i; 00381 00382 if (start == -1) 00383 { 00384 start = 0; 00385 end = stk->nb_points - 1; 00386 } 00387 00388 sk_allocStrokeBuffer(stk); 00389 stk->nb_points = 0; 00390 00391 /* adding points before range */ 00392 for (i = 0; i < start; i++) 00393 { 00394 sk_appendStrokePoint(stk, old_points + i); 00395 } 00396 00397 marked = MEM_callocN(nb_points, "marked array"); 00398 marked[start] = 1; 00399 marked[end] = 1; 00400 00401 work = 1; 00402 00403 /* while still reducing */ 00404 while (work) 00405 { 00406 int ls, le; 00407 work = 0; 00408 00409 ls = start; 00410 le = start+1; 00411 00412 /* while not over interval */ 00413 while (ls < end) 00414 { 00415 int max_i = 0; 00416 short v1[2]; 00417 float max_dist = 16; /* more than 4 pixels */ 00418 00419 /* find the next marked point */ 00420 while(marked[le] == 0) 00421 { 00422 le++; 00423 } 00424 00425 /* perpendicular vector to ls-le */ 00426 v1[1] = old_points[le].p2d[0] - old_points[ls].p2d[0]; 00427 v1[0] = old_points[ls].p2d[1] - old_points[le].p2d[1]; 00428 00429 00430 for( i = ls + 1; i < le; i++ ) 00431 { 00432 float mul; 00433 float dist; 00434 short v2[2]; 00435 00436 v2[0] = old_points[i].p2d[0] - old_points[ls].p2d[0]; 00437 v2[1] = old_points[i].p2d[1] - old_points[ls].p2d[1]; 00438 00439 if (v2[0] == 0 && v2[1] == 0) 00440 { 00441 continue; 00442 } 00443 00444 mul = (float)(v1[0]*v2[0] + v1[1]*v2[1]) / (float)(v2[0]*v2[0] + v2[1]*v2[1]); 00445 00446 dist = mul * mul * (v2[0]*v2[0] + v2[1]*v2[1]); 00447 00448 if (dist > max_dist) 00449 { 00450 max_dist = dist; 00451 max_i = i; 00452 } 00453 } 00454 00455 if (max_i != 0) 00456 { 00457 work = 1; 00458 marked[max_i] = 1; 00459 } 00460 00461 ls = le; 00462 le = ls + 1; 00463 } 00464 } 00465 00466 00467 /* adding points after range */ 00468 for (i = start; i <= end; i++) 00469 { 00470 if (marked[i]) 00471 { 00472 sk_appendStrokePoint(stk, old_points + i); 00473 } 00474 } 00475 00476 MEM_freeN(marked); 00477 00478 /* adding points after range */ 00479 for (i = end + 1; i < nb_points; i++) 00480 { 00481 sk_appendStrokePoint(stk, old_points + i); 00482 } 00483 00484 MEM_freeN(old_points); 00485 00486 sk_shrinkStrokeBuffer(stk); 00487 } 00488 00489 00490 void sk_filterLastContinuousStroke(SK_Stroke *stk) 00491 { 00492 int start, end; 00493 00494 end = stk->nb_points -1; 00495 00496 for (start = end - 1; start > 0 && stk->points[start].type == PT_CONTINUOUS; start--) 00497 { 00498 /* nothing to do here*/ 00499 } 00500 00501 if (end - start > 1) 00502 { 00503 sk_filterStroke(stk, start, end); 00504 } 00505 } 00506 00507 SK_Point *sk_lastStrokePoint(SK_Stroke *stk) 00508 { 00509 SK_Point *pt = NULL; 00510 00511 if (stk->nb_points > 0) 00512 { 00513 pt = stk->points + (stk->nb_points - 1); 00514 } 00515 00516 return pt; 00517 } 00518 00519 void sk_endContinuousStroke(SK_Stroke *stk) 00520 { 00521 stk->points[stk->nb_points - 1].type = PT_EXACT; 00522 } 00523 00524 void sk_updateNextPoint(SK_Sketch *sketch, SK_Stroke *stk) 00525 { 00526 if (stk) 00527 { 00528 memcpy(&sketch->next_point, stk->points[stk->nb_points - 1].p, sizeof(SK_Point)); 00529 } 00530 } 00531 00532 int sk_stroke_filtermval(SK_DrawData *dd) 00533 { 00534 int retval = 0; 00535 if (ABS(dd->mval[0] - dd->previous_mval[0]) + ABS(dd->mval[1] - dd->previous_mval[1]) > U.gp_manhattendist) 00536 { 00537 retval = 1; 00538 } 00539 00540 return retval; 00541 } 00542 00543 void sk_initDrawData(SK_DrawData *dd, const int mval[2]) 00544 { 00545 dd->mval[0] = mval[0]; 00546 dd->mval[1] = mval[1]; 00547 dd->previous_mval[0] = -1; 00548 dd->previous_mval[1] = -1; 00549 dd->type = PT_EXACT; 00550 } 00551 00552 00553 void sk_deleteSelectedStrokes(SK_Sketch *sketch) 00554 { 00555 SK_Stroke *stk, *next; 00556 00557 for (stk = sketch->strokes.first; stk; stk = next) 00558 { 00559 next = stk->next; 00560 00561 if (stk->selected == 1) 00562 { 00563 sk_removeStroke(sketch, stk); 00564 } 00565 } 00566 } 00567 00568 void sk_selectAllSketch(SK_Sketch *sketch, int mode) 00569 { 00570 SK_Stroke *stk = NULL; 00571 00572 if (mode == -1) 00573 { 00574 for (stk = sketch->strokes.first; stk; stk = stk->next) 00575 { 00576 stk->selected = 0; 00577 } 00578 } 00579 else if (mode == 0) 00580 { 00581 for (stk = sketch->strokes.first; stk; stk = stk->next) 00582 { 00583 stk->selected = 1; 00584 } 00585 } 00586 else if (mode == 1) 00587 { 00588 int selected = 1; 00589 00590 for (stk = sketch->strokes.first; stk; stk = stk->next) 00591 { 00592 selected &= stk->selected; 00593 } 00594 00595 selected ^= 1; 00596 00597 for (stk = sketch->strokes.first; stk; stk = stk->next) 00598 { 00599 stk->selected = selected; 00600 } 00601 } 00602 }