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