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 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): Jiri Hnidek <jiri.hnidek@vslib.cz>. 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 * 00025 * MetaBalls are created from a single Object (with a name without number in it), 00026 * here the DispList and BoundBox also is located. 00027 * All objects with the same name (but with a number in it) are added to this. 00028 * 00029 * texture coordinates are patched within the displist 00030 */ 00031 00036 #include <stdio.h> 00037 #include <string.h> 00038 #include <math.h> 00039 #include <stdlib.h> 00040 #include <ctype.h> 00041 #include <float.h> 00042 #include "MEM_guardedalloc.h" 00043 00044 #include "DNA_material_types.h" 00045 #include "DNA_object_types.h" 00046 #include "DNA_meta_types.h" 00047 #include "DNA_scene_types.h" 00048 00049 00050 #include "BLI_blenlib.h" 00051 #include "BLI_math.h" 00052 #include "BLI_utildefines.h" 00053 #include "BLI_bpath.h" 00054 00055 00056 #include "BKE_global.h" 00057 #include "BKE_main.h" 00058 00059 /* #include "BKE_object.h" */ 00060 #include "BKE_animsys.h" 00061 #include "BKE_scene.h" 00062 #include "BKE_library.h" 00063 #include "BKE_displist.h" 00064 #include "BKE_mball.h" 00065 #include "BKE_object.h" 00066 #include "BKE_material.h" 00067 00068 /* Global variables */ 00069 00070 static float thresh= 0.6f; 00071 static int totelem=0; 00072 static MetaElem **mainb; 00073 static octal_tree *metaball_tree = NULL; 00074 /* Functions */ 00075 00076 void unlink_mball(MetaBall *mb) 00077 { 00078 int a; 00079 00080 for(a=0; a<mb->totcol; a++) { 00081 if(mb->mat[a]) mb->mat[a]->id.us--; 00082 mb->mat[a]= NULL; 00083 } 00084 } 00085 00086 00087 /* do not free mball itself */ 00088 void free_mball(MetaBall *mb) 00089 { 00090 unlink_mball(mb); 00091 00092 if(mb->adt) { 00093 BKE_free_animdata((ID *)mb); 00094 mb->adt = NULL; 00095 } 00096 if(mb->mat) MEM_freeN(mb->mat); 00097 if(mb->bb) MEM_freeN(mb->bb); 00098 BLI_freelistN(&mb->elems); 00099 if(mb->disp.first) freedisplist(&mb->disp); 00100 } 00101 00102 MetaBall *add_mball(const char *name) 00103 { 00104 MetaBall *mb; 00105 00106 mb= alloc_libblock(&G.main->mball, ID_MB, name); 00107 00108 mb->size[0]= mb->size[1]= mb->size[2]= 1.0; 00109 mb->texflag= MB_AUTOSPACE; 00110 00111 mb->wiresize= 0.4f; 00112 mb->rendersize= 0.2f; 00113 mb->thresh= 0.6f; 00114 00115 return mb; 00116 } 00117 00118 MetaBall *copy_mball(MetaBall *mb) 00119 { 00120 MetaBall *mbn; 00121 int a; 00122 00123 mbn= copy_libblock(&mb->id); 00124 00125 BLI_duplicatelist(&mbn->elems, &mb->elems); 00126 00127 mbn->mat= MEM_dupallocN(mb->mat); 00128 for(a=0; a<mbn->totcol; a++) { 00129 id_us_plus((ID *)mbn->mat[a]); 00130 } 00131 mbn->bb= MEM_dupallocN(mb->bb); 00132 00133 mbn->editelems= NULL; 00134 mbn->lastelem= NULL; 00135 00136 return mbn; 00137 } 00138 00139 static void extern_local_mball(MetaBall *mb) 00140 { 00141 if(mb->mat) { 00142 extern_local_matarar(mb->mat, mb->totcol); 00143 } 00144 } 00145 00146 void make_local_mball(MetaBall *mb) 00147 { 00148 Main *bmain= G.main; 00149 Object *ob; 00150 int is_local= FALSE, is_lib= FALSE; 00151 00152 /* - only lib users: do nothing 00153 * - only local users: set flag 00154 * - mixed: make copy 00155 */ 00156 00157 if(mb->id.lib==NULL) return; 00158 if(mb->id.us==1) { 00159 id_clear_lib_data(bmain, &mb->id); 00160 extern_local_mball(mb); 00161 00162 return; 00163 } 00164 00165 for(ob= G.main->object.first; ob && ELEM(0, is_lib, is_local); ob= ob->id.next) { 00166 if(ob->data == mb) { 00167 if(ob->id.lib) is_lib= TRUE; 00168 else is_local= TRUE; 00169 } 00170 } 00171 00172 if(is_local && is_lib == FALSE) { 00173 id_clear_lib_data(bmain, &mb->id); 00174 extern_local_mball(mb); 00175 } 00176 else if(is_local && is_lib) { 00177 MetaBall *mb_new= copy_mball(mb); 00178 mb_new->id.us= 0; 00179 00180 /* Remap paths of new ID using old library as base. */ 00181 BKE_id_lib_local_paths(bmain, mb->id.lib, &mb_new->id); 00182 00183 for(ob= G.main->object.first; ob; ob= ob->id.next) { 00184 if(ob->data == mb) { 00185 if(ob->id.lib==NULL) { 00186 ob->data= mb_new; 00187 mb_new->id.us++; 00188 mb->id.us--; 00189 } 00190 } 00191 } 00192 } 00193 } 00194 00195 /* most simple meta-element adding function 00196 * don't do context manipulation here (rna uses) */ 00197 MetaElem *add_metaball_element(MetaBall *mb, const int type) 00198 { 00199 MetaElem *ml= MEM_callocN(sizeof(MetaElem), "metaelem"); 00200 00201 unit_qt(ml->quat); 00202 00203 ml->rad= 2.0; 00204 ml->s= 2.0; 00205 ml->flag= MB_SCALE_RAD; 00206 00207 switch(type) { 00208 case MB_BALL: 00209 ml->type = MB_BALL; 00210 ml->expx= ml->expy= ml->expz= 1.0; 00211 00212 break; 00213 case MB_TUBE: 00214 ml->type = MB_TUBE; 00215 ml->expx= ml->expy= ml->expz= 1.0; 00216 00217 break; 00218 case MB_PLANE: 00219 ml->type = MB_PLANE; 00220 ml->expx= ml->expy= ml->expz= 1.0; 00221 00222 break; 00223 case MB_ELIPSOID: 00224 ml->type = MB_ELIPSOID; 00225 ml->expx= 1.2f; 00226 ml->expy= 0.8f; 00227 ml->expz= 1.0; 00228 00229 break; 00230 case MB_CUBE: 00231 ml->type = MB_CUBE; 00232 ml->expx= ml->expy= ml->expz= 1.0; 00233 00234 break; 00235 default: 00236 break; 00237 } 00238 00239 BLI_addtail(&mb->elems, ml); 00240 00241 return ml; 00242 } 00249 void tex_space_mball(Object *ob) 00250 { 00251 DispList *dl; 00252 BoundBox *bb; 00253 float *data, min[3], max[3] /*, loc[3], size[3] */; 00254 int tot, doit=0; 00255 00256 if(ob->bb==NULL) ob->bb= MEM_callocN(sizeof(BoundBox), "mb boundbox"); 00257 bb= ob->bb; 00258 00259 /* Weird one, this. */ 00260 /* INIT_MINMAX(min, max); */ 00261 (min)[0]= (min)[1]= (min)[2]= 1.0e30f; 00262 (max)[0]= (max)[1]= (max)[2]= -1.0e30f; 00263 00264 dl= ob->disp.first; 00265 while(dl) { 00266 tot= dl->nr; 00267 if(tot) doit= 1; 00268 data= dl->verts; 00269 while(tot--) { 00270 /* Also weird... but longer. From utildefines. */ 00271 DO_MINMAX(data, min, max); 00272 data+= 3; 00273 } 00274 dl= dl->next; 00275 } 00276 00277 if(!doit) { 00278 min[0] = min[1] = min[2] = -1.0f; 00279 max[0] = max[1] = max[2] = 1.0f; 00280 } 00281 /* 00282 loc[0]= (min[0]+max[0])/2.0f; 00283 loc[1]= (min[1]+max[1])/2.0f; 00284 loc[2]= (min[2]+max[2])/2.0f; 00285 00286 size[0]= (max[0]-min[0])/2.0f; 00287 size[1]= (max[1]-min[1])/2.0f; 00288 size[2]= (max[2]-min[2])/2.0f; 00289 */ 00290 boundbox_set_from_min_max(bb, min, max); 00291 } 00292 00293 float *make_orco_mball(Object *ob, ListBase *dispbase) 00294 { 00295 BoundBox *bb; 00296 DispList *dl; 00297 float *data, *orco, *orcodata; 00298 float loc[3], size[3]; 00299 int a; 00300 00301 /* restore size and loc */ 00302 bb= ob->bb; 00303 loc[0]= (bb->vec[0][0]+bb->vec[4][0])/2.0f; 00304 size[0]= bb->vec[4][0]-loc[0]; 00305 loc[1]= (bb->vec[0][1]+bb->vec[2][1])/2.0f; 00306 size[1]= bb->vec[2][1]-loc[1]; 00307 loc[2]= (bb->vec[0][2]+bb->vec[1][2])/2.0f; 00308 size[2]= bb->vec[1][2]-loc[2]; 00309 00310 dl= dispbase->first; 00311 orcodata= MEM_mallocN(sizeof(float)*3*dl->nr, "MballOrco"); 00312 00313 data= dl->verts; 00314 orco= orcodata; 00315 a= dl->nr; 00316 while(a--) { 00317 orco[0]= (data[0]-loc[0])/size[0]; 00318 orco[1]= (data[1]-loc[1])/size[1]; 00319 orco[2]= (data[2]-loc[2])/size[2]; 00320 00321 data+= 3; 00322 orco+= 3; 00323 } 00324 00325 return orcodata; 00326 } 00327 00328 /* Note on mball basis stuff 2.5x (this is a can of worms) 00329 * This really needs a rewrite/refactor its totally broken in anything other then basic cases 00330 * Multiple Scenes + Set Scenes & mixing mball basis SHOULD work but fails to update the depsgraph on rename 00331 * and linking into scenes or removal of basis mball. so take care when changing this code. 00332 * 00333 * Main idiot thing here is that the system returns find_basis_mball() objects which fail a is_basis_mball() test. 00334 * 00335 * Not only that but the depsgraph and their areas depend on this behavior!, so making small fixes here isn't worth it. 00336 * - Campbell 00337 */ 00338 00339 00345 int is_basis_mball(Object *ob) 00346 { 00347 int len; 00348 00349 /* just a quick test */ 00350 len= strlen(ob->id.name); 00351 if( isdigit(ob->id.name[len-1]) ) return 0; 00352 return 1; 00353 } 00354 00355 /* return nonzero if ob1 is a basis mball for ob */ 00356 int is_mball_basis_for(Object *ob1, Object *ob2) 00357 { 00358 int basis1nr, basis2nr; 00359 char basis1name[MAX_ID_NAME], basis2name[MAX_ID_NAME]; 00360 00361 BLI_split_name_num(basis1name, &basis1nr, ob1->id.name+2, '.'); 00362 BLI_split_name_num(basis2name, &basis2nr, ob2->id.name+2, '.'); 00363 00364 if(!strcmp(basis1name, basis2name)) return is_basis_mball(ob1); 00365 else return 0; 00366 } 00367 00368 /* \brief copy some properties from object to other metaball object with same base name 00369 * 00370 * When some properties (wiresize, threshold, update flags) of metaball are changed, then this properties 00371 * are copied to all metaballs in same "group" (metaballs with same base name: MBall, 00372 * MBall.001, MBall.002, etc). The most important is to copy properties to the base metaball, 00373 * because this metaball influence polygonisation of metaballs. */ 00374 void copy_mball_properties(Scene *scene, Object *active_object) 00375 { 00376 Scene *sce_iter= scene; 00377 Base *base; 00378 Object *ob; 00379 MetaBall *active_mball = (MetaBall*)active_object->data; 00380 int basisnr, obnr; 00381 char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; 00382 00383 BLI_split_name_num(basisname, &basisnr, active_object->id.name+2, '.'); 00384 00385 /* XXX recursion check, see scene.c, just too simple code this next_object() */ 00386 if(F_ERROR==next_object(&sce_iter, 0, NULL, NULL)) 00387 return; 00388 00389 while(next_object(&sce_iter, 1, &base, &ob)) { 00390 if (ob->type==OB_MBALL) { 00391 if(ob!=active_object){ 00392 BLI_split_name_num(obname, &obnr, ob->id.name+2, '.'); 00393 00394 /* Object ob has to be in same "group" ... it means, that it has to have 00395 * same base of its name */ 00396 if(strcmp(obname, basisname)==0){ 00397 MetaBall *mb= ob->data; 00398 00399 /* Copy properties from selected/edited metaball */ 00400 mb->wiresize= active_mball->wiresize; 00401 mb->rendersize= active_mball->rendersize; 00402 mb->thresh= active_mball->thresh; 00403 mb->flag= active_mball->flag; 00404 } 00405 } 00406 } 00407 } 00408 } 00409 00419 Object *find_basis_mball(Scene *scene, Object *basis) 00420 { 00421 Scene *sce_iter= scene; 00422 Base *base; 00423 Object *ob,*bob= basis; 00424 MetaElem *ml=NULL; 00425 int basisnr, obnr; 00426 char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; 00427 00428 BLI_split_name_num(basisname, &basisnr, basis->id.name+2, '.'); 00429 totelem= 0; 00430 00431 /* XXX recursion check, see scene.c, just too simple code this next_object() */ 00432 if(F_ERROR==next_object(&sce_iter, 0, NULL, NULL)) 00433 return NULL; 00434 00435 while(next_object(&sce_iter, 1, &base, &ob)) { 00436 00437 if (ob->type==OB_MBALL) { 00438 if(ob==bob){ 00439 MetaBall *mb= ob->data; 00440 00441 /* if bob object is in edit mode, then dynamic list of all MetaElems 00442 * is stored in editelems */ 00443 if(mb->editelems) ml= mb->editelems->first; 00444 /* if bob object is in object mode */ 00445 else ml= mb->elems.first; 00446 } 00447 else{ 00448 BLI_split_name_num(obname, &obnr, ob->id.name+2, '.'); 00449 00450 /* object ob has to be in same "group" ... it means, that it has to have 00451 * same base of its name */ 00452 if(strcmp(obname, basisname)==0){ 00453 MetaBall *mb= ob->data; 00454 00455 /* if object is in edit mode, then dynamic list of all MetaElems 00456 * is stored in editelems */ 00457 if(mb->editelems) ml= mb->editelems->first; 00458 /* if bob object is in object mode */ 00459 else ml= mb->elems.first; 00460 00461 if(obnr<basisnr){ 00462 if(!(ob->flag & OB_FROMDUPLI)){ 00463 basis= ob; 00464 basisnr= obnr; 00465 } 00466 } 00467 } 00468 } 00469 00470 while(ml){ 00471 if(!(ml->flag & MB_HIDE)) totelem++; 00472 ml= ml->next; 00473 } 00474 } 00475 } 00476 00477 return basis; 00478 } 00479 00480 00481 /* ******************** ARITH ************************* */ 00482 00483 /* BASED AT CODE (but mostly rewritten) : 00484 * C code from the article 00485 * "An Implicit Surface Polygonizer" 00486 * by Jules Bloomenthal, jbloom@beauty.gmu.edu 00487 * in "Graphics Gems IV", Academic Press, 1994 00488 00489 * Authored by Jules Bloomenthal, Xerox PARC. 00490 * Copyright (c) Xerox Corporation, 1991. All rights reserved. 00491 * Permission is granted to reproduce, use and distribute this code for 00492 * any and all purposes, provided that this notice appears in all copies. */ 00493 00494 #define RES 12 /* # converge iterations */ 00495 00496 #define L 0 /* left direction: -x, -i */ 00497 #define R 1 /* right direction: +x, +i */ 00498 #define B 2 /* bottom direction: -y, -j */ 00499 #define T 3 /* top direction: +y, +j */ 00500 #define N 4 /* near direction: -z, -k */ 00501 #define F 5 /* far direction: +z, +k */ 00502 #define LBN 0 /* left bottom near corner */ 00503 #define LBF 1 /* left bottom far corner */ 00504 #define LTN 2 /* left top near corner */ 00505 #define LTF 3 /* left top far corner */ 00506 #define RBN 4 /* right bottom near corner */ 00507 #define RBF 5 /* right bottom far corner */ 00508 #define RTN 6 /* right top near corner */ 00509 #define RTF 7 /* right top far corner */ 00510 00511 /* the LBN corner of cube (i, j, k), corresponds with location 00512 * (i-0.5)*size, (j-0.5)*size, (k-0.5)*size) */ 00513 00514 #define HASHBIT (5) 00515 #define HASHSIZE (size_t)(1<<(3*HASHBIT)) 00517 #define HASH(i,j,k) ((((( (i) & 31)<<5) | ( (j) & 31))<<5 ) | ( (k) & 31) ) 00518 00519 #define MB_BIT(i, bit) (((i)>>(bit))&1) 00520 #define FLIP(i,bit) ((i)^1<<(bit)) /* flip the given bit of i */ 00521 00522 00523 /* **************** POLYGONIZATION ************************ */ 00524 00525 void calc_mballco(MetaElem *ml, float *vec) 00526 { 00527 if(ml->mat) { 00528 mul_m4_v3((float ( * )[4])ml->mat, vec); 00529 } 00530 } 00531 00532 float densfunc(MetaElem *ball, float x, float y, float z) 00533 { 00534 float dist2 = 0.0, dx, dy, dz; 00535 float vec[3]; 00536 00537 vec[0]= x; 00538 vec[1]= y; 00539 vec[2]= z; 00540 mul_m4_v3((float ( * )[4])ball->imat, vec); 00541 dx= vec[0]; 00542 dy= vec[1]; 00543 dz= vec[2]; 00544 00545 if(ball->type==MB_BALL) { 00546 } 00547 else if(ball->type==MB_TUBEX) { 00548 if( dx > ball->len) dx-= ball->len; 00549 else if(dx< -ball->len) dx+= ball->len; 00550 else dx= 0.0; 00551 } 00552 else if(ball->type==MB_TUBEY) { 00553 if( dy > ball->len) dy-= ball->len; 00554 else if(dy< -ball->len) dy+= ball->len; 00555 else dy= 0.0; 00556 } 00557 else if(ball->type==MB_TUBEZ) { 00558 if( dz > ball->len) dz-= ball->len; 00559 else if(dz< -ball->len) dz+= ball->len; 00560 else dz= 0.0; 00561 } 00562 else if(ball->type==MB_TUBE) { 00563 if( dx > ball->expx) dx-= ball->expx; 00564 else if(dx< -ball->expx) dx+= ball->expx; 00565 else dx= 0.0; 00566 } 00567 else if(ball->type==MB_PLANE) { 00568 if( dx > ball->expx) dx-= ball->expx; 00569 else if(dx< -ball->expx) dx+= ball->expx; 00570 else dx= 0.0; 00571 if( dy > ball->expy) dy-= ball->expy; 00572 else if(dy< -ball->expy) dy+= ball->expy; 00573 else dy= 0.0; 00574 } 00575 else if(ball->type==MB_ELIPSOID) { 00576 dx *= 1/ball->expx; 00577 dy *= 1/ball->expy; 00578 dz *= 1/ball->expz; 00579 } 00580 else if(ball->type==MB_CUBE) { 00581 if( dx > ball->expx) dx-= ball->expx; 00582 else if(dx< -ball->expx) dx+= ball->expx; 00583 else dx= 0.0; 00584 if( dy > ball->expy) dy-= ball->expy; 00585 else if(dy< -ball->expy) dy+= ball->expy; 00586 else dy= 0.0; 00587 if( dz > ball->expz) dz-= ball->expz; 00588 else if(dz< -ball->expz) dz+= ball->expz; 00589 else dz= 0.0; 00590 } 00591 00592 dist2= (dx*dx + dy*dy + dz*dz); 00593 00594 if(ball->flag & MB_NEGATIVE) { 00595 dist2= 1.0f-(dist2/ball->rad2); 00596 if(dist2 < 0.0f) return 0.5f; 00597 00598 return 0.5f-ball->s*dist2*dist2*dist2; 00599 } 00600 else { 00601 dist2= 1.0f-(dist2/ball->rad2); 00602 if(dist2 < 0.0f) return -0.5f; 00603 00604 return ball->s*dist2*dist2*dist2 -0.5f; 00605 } 00606 } 00607 00608 octal_node* find_metaball_octal_node(octal_node *node, float x, float y, float z, short depth) 00609 { 00610 if(!depth) return node; 00611 00612 if(z < node->z){ 00613 if(y < node->y){ 00614 if(x < node->x){ 00615 if(node->nodes[0]) 00616 return find_metaball_octal_node(node->nodes[0],x,y,z,depth--); 00617 else 00618 return node; 00619 } 00620 else{ 00621 if(node->nodes[1]) 00622 return find_metaball_octal_node(node->nodes[1],x,y,z,depth--); 00623 else 00624 return node; 00625 } 00626 } 00627 else{ 00628 if(x < node->x){ 00629 if(node->nodes[3]) 00630 return find_metaball_octal_node(node->nodes[3],x,y,z,depth--); 00631 else 00632 return node; 00633 } 00634 else{ 00635 if(node->nodes[2]) 00636 return find_metaball_octal_node(node->nodes[2],x,y,z,depth--); 00637 else 00638 return node; 00639 } 00640 } 00641 } 00642 else{ 00643 if(y < node->y){ 00644 if(x < node->x){ 00645 if(node->nodes[4]) 00646 return find_metaball_octal_node(node->nodes[4],x,y,z,depth--); 00647 else 00648 return node; 00649 } 00650 else{ 00651 if(node->nodes[5]) 00652 return find_metaball_octal_node(node->nodes[5],x,y,z,depth--); 00653 else 00654 return node; 00655 } 00656 } 00657 else{ 00658 if(x < node->x){ 00659 if(node->nodes[7]) 00660 return find_metaball_octal_node(node->nodes[7],x,y,z,depth--); 00661 else 00662 return node; 00663 } 00664 else{ 00665 if(node->nodes[6]) 00666 return find_metaball_octal_node(node->nodes[6],x,y,z,depth--); 00667 else 00668 return node; 00669 } 00670 } 00671 } 00672 00673 return node; 00674 } 00675 00676 float metaball(float x, float y, float z) 00677 /* float x, y, z; */ 00678 { 00679 struct octal_node *node; 00680 struct ml_pointer *ml_p; 00681 float dens=0; 00682 int a; 00683 00684 if(totelem > 1){ 00685 node= find_metaball_octal_node(metaball_tree->first, x, y, z, metaball_tree->depth); 00686 if(node){ 00687 ml_p= node->elems.first; 00688 00689 while(ml_p){ 00690 dens+=densfunc(ml_p->ml, x, y, z); 00691 ml_p= ml_p->next; 00692 } 00693 00694 dens+= -0.5f*(metaball_tree->pos - node->pos); 00695 dens+= 0.5f*(metaball_tree->neg - node->neg); 00696 } 00697 else{ 00698 for(a=0; a<totelem; a++) { 00699 dens+= densfunc( mainb[a], x, y, z); 00700 } 00701 } 00702 } 00703 else{ 00704 dens+= densfunc( mainb[0], x, y, z); 00705 } 00706 00707 return thresh - dens; 00708 } 00709 00710 /* ******************************************** */ 00711 00712 static int *indices=NULL; 00713 static int totindex, curindex; 00714 00715 00716 void accum_mballfaces(int i1, int i2, int i3, int i4) 00717 { 00718 int *newi, *cur; 00719 /* static int i=0; I would like to delete altogether, but I don't dare to, yet */ 00720 00721 if(totindex==curindex) { 00722 totindex+= 256; 00723 newi= MEM_mallocN(4*sizeof(int)*totindex, "vertindex"); 00724 00725 if(indices) { 00726 memcpy(newi, indices, 4*sizeof(int)*(totindex-256)); 00727 MEM_freeN(indices); 00728 } 00729 indices= newi; 00730 } 00731 00732 cur= indices+4*curindex; 00733 00734 /* displists now support array drawing, we treat tri's as fake quad */ 00735 00736 cur[0]= i1; 00737 cur[1]= i2; 00738 cur[2]= i3; 00739 if(i4==0) 00740 cur[3]= i3; 00741 else 00742 cur[3]= i4; 00743 00744 curindex++; 00745 00746 } 00747 00748 /* ******************* MEMORY MANAGEMENT *********************** */ 00749 void *new_pgn_element(int size) 00750 { 00751 /* during polygonize 1000s of elements are allocated 00752 * and never freed in between. Freeing only done at the end. 00753 */ 00754 int blocksize= 16384; 00755 static int offs= 0; /* the current free address */ 00756 static struct pgn_elements *cur= NULL; 00757 static ListBase lb= {NULL, NULL}; 00758 void *adr; 00759 00760 if(size>10000 || size==0) { 00761 printf("incorrect use of new_pgn_element\n"); 00762 } 00763 else if(size== -1) { 00764 cur= lb.first; 00765 while(cur) { 00766 MEM_freeN(cur->data); 00767 cur= cur->next; 00768 } 00769 BLI_freelistN(&lb); 00770 00771 return NULL; 00772 } 00773 00774 size= 4*( (size+3)/4 ); 00775 00776 if(cur) { 00777 if(size+offs < blocksize) { 00778 adr= (void *) (cur->data+offs); 00779 offs+= size; 00780 return adr; 00781 } 00782 } 00783 00784 cur= MEM_callocN( sizeof(struct pgn_elements), "newpgn"); 00785 cur->data= MEM_callocN(blocksize, "newpgn"); 00786 BLI_addtail(&lb, cur); 00787 00788 offs= size; 00789 return cur->data; 00790 } 00791 00792 void freepolygonize(PROCESS *p) 00793 { 00794 MEM_freeN(p->corners); 00795 MEM_freeN(p->edges); 00796 MEM_freeN(p->centers); 00797 00798 new_pgn_element(-1); 00799 00800 if(p->vertices.ptr) MEM_freeN(p->vertices.ptr); 00801 } 00802 00803 /**** Cubical Polygonization (optional) ****/ 00804 00805 #define LB 0 /* left bottom edge */ 00806 #define LT 1 /* left top edge */ 00807 #define LN 2 /* left near edge */ 00808 #define LF 3 /* left far edge */ 00809 #define RB 4 /* right bottom edge */ 00810 #define RT 5 /* right top edge */ 00811 #define RN 6 /* right near edge */ 00812 #define RF 7 /* right far edge */ 00813 #define BN 8 /* bottom near edge */ 00814 #define BF 9 /* bottom far edge */ 00815 #define TN 10 /* top near edge */ 00816 #define TF 11 /* top far edge */ 00817 00818 static INTLISTS *cubetable[256]; 00819 00820 /* edge: LB, LT, LN, LF, RB, RT, RN, RF, BN, BF, TN, TF */ 00821 static int corner1[12] = { 00822 LBN,LTN,LBN,LBF,RBN,RTN,RBN,RBF,LBN,LBF,LTN,LTF}; 00823 static int corner2[12] = { 00824 LBF,LTF,LTN,LTF,RBF,RTF,RTN,RTF,RBN,RBF,RTN,RTF}; 00825 static int leftface[12] = { 00826 B, L, L, F, R, T, N, R, N, B, T, F}; 00827 /* face on left when going corner1 to corner2 */ 00828 static int rightface[12] = { 00829 L, T, N, L, B, R, R, F, B, F, N, T}; 00830 /* face on right when going corner1 to corner2 */ 00831 00832 00833 /* docube: triangulate the cube directly, without decomposition */ 00834 00835 void docube(CUBE *cube, PROCESS *p, MetaBall *mb) 00836 { 00837 INTLISTS *polys; 00838 CORNER *c1, *c2; 00839 int i, index = 0, count, indexar[8]; 00840 00841 for (i = 0; i < 8; i++) if (cube->corners[i]->value > 0.0f) index += (1<<i); 00842 00843 for (polys = cubetable[index]; polys; polys = polys->next) { 00844 INTLIST *edges; 00845 00846 count = 0; 00847 00848 for (edges = polys->list; edges; edges = edges->next) { 00849 c1 = cube->corners[corner1[edges->i]]; 00850 c2 = cube->corners[corner2[edges->i]]; 00851 00852 indexar[count] = vertid(c1, c2, p, mb); 00853 count++; 00854 } 00855 if(count>2) { 00856 switch(count) { 00857 case 3: 00858 accum_mballfaces(indexar[2], indexar[1], indexar[0], 0); 00859 break; 00860 case 4: 00861 if(indexar[0]==0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); 00862 else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); 00863 break; 00864 case 5: 00865 if(indexar[0]==0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); 00866 else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); 00867 00868 accum_mballfaces(indexar[4], indexar[3], indexar[0], 0); 00869 break; 00870 case 6: 00871 if(indexar[0]==0) { 00872 accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); 00873 accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]); 00874 } 00875 else { 00876 accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); 00877 accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]); 00878 } 00879 break; 00880 case 7: 00881 if(indexar[0]==0) { 00882 accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); 00883 accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]); 00884 } 00885 else { 00886 accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); 00887 accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]); 00888 } 00889 00890 accum_mballfaces(indexar[6], indexar[5], indexar[0], 0); 00891 00892 break; 00893 } 00894 } 00895 } 00896 } 00897 00898 00899 /* testface: given cube at lattice (i, j, k), and four corners of face, 00900 * if surface crosses face, compute other four corners of adjacent cube 00901 * and add new cube to cube stack */ 00902 00903 void testface(int i, int j, int k, CUBE* old, int bit, int c1, int c2, int c3, int c4, PROCESS *p) 00904 { 00905 CUBE newc; 00906 CUBES *oldcubes = p->cubes; 00907 CORNER *corn1, *corn2, *corn3, *corn4; 00908 int n, pos; 00909 00910 corn1= old->corners[c1]; 00911 corn2= old->corners[c2]; 00912 corn3= old->corners[c3]; 00913 corn4= old->corners[c4]; 00914 00915 pos = corn1->value > 0.0f ? 1 : 0; 00916 00917 /* test if no surface crossing */ 00918 if( (corn2->value > 0) == pos && (corn3->value > 0) == pos && (corn4->value > 0) == pos) return; 00919 /* test if cube out of bounds */ 00920 /*if ( abs(i) > p->bounds || abs(j) > p->bounds || abs(k) > p->bounds) return;*/ 00921 /* test if already visited (always as last) */ 00922 if (setcenter(p->centers, i, j, k)) return; 00923 00924 00925 /* create new cube and add cube to top of stack: */ 00926 p->cubes = (CUBES *) new_pgn_element(sizeof(CUBES)); 00927 p->cubes->next = oldcubes; 00928 00929 newc.i = i; 00930 newc.j = j; 00931 newc.k = k; 00932 for (n = 0; n < 8; n++) newc.corners[n] = NULL; 00933 00934 newc.corners[FLIP(c1, bit)] = corn1; 00935 newc.corners[FLIP(c2, bit)] = corn2; 00936 newc.corners[FLIP(c3, bit)] = corn3; 00937 newc.corners[FLIP(c4, bit)] = corn4; 00938 00939 if(newc.corners[0]==NULL) newc.corners[0] = setcorner(p, i, j, k); 00940 if(newc.corners[1]==NULL) newc.corners[1] = setcorner(p, i, j, k+1); 00941 if(newc.corners[2]==NULL) newc.corners[2] = setcorner(p, i, j+1, k); 00942 if(newc.corners[3]==NULL) newc.corners[3] = setcorner(p, i, j+1, k+1); 00943 if(newc.corners[4]==NULL) newc.corners[4] = setcorner(p, i+1, j, k); 00944 if(newc.corners[5]==NULL) newc.corners[5] = setcorner(p, i+1, j, k+1); 00945 if(newc.corners[6]==NULL) newc.corners[6] = setcorner(p, i+1, j+1, k); 00946 if(newc.corners[7]==NULL) newc.corners[7] = setcorner(p, i+1, j+1, k+1); 00947 00948 p->cubes->cube= newc; 00949 } 00950 00951 /* setcorner: return corner with the given lattice location 00952 set (and cache) its function value */ 00953 00954 CORNER *setcorner (PROCESS* p, int i, int j, int k) 00955 { 00956 /* for speed, do corner value caching here */ 00957 CORNER *c; 00958 int index; 00959 00960 /* does corner exist? */ 00961 index = HASH(i, j, k); 00962 c = p->corners[index]; 00963 00964 for (; c != NULL; c = c->next) { 00965 if (c->i == i && c->j == j && c->k == k) { 00966 return c; 00967 } 00968 } 00969 00970 c = (CORNER *) new_pgn_element(sizeof(CORNER)); 00971 00972 c->i = i; 00973 c->x = ((float)i-0.5f)*p->size; 00974 c->j = j; 00975 c->y = ((float)j-0.5f)*p->size; 00976 c->k = k; 00977 c->z = ((float)k-0.5f)*p->size; 00978 c->value = p->function(c->x, c->y, c->z); 00979 00980 c->next = p->corners[index]; 00981 p->corners[index] = c; 00982 00983 return c; 00984 } 00985 00986 00987 /* nextcwedge: return next clockwise edge from given edge around given face */ 00988 00989 int nextcwedge (int edge, int face) 00990 { 00991 switch (edge) { 00992 case LB: 00993 return (face == L)? LF : BN; 00994 case LT: 00995 return (face == L)? LN : TF; 00996 case LN: 00997 return (face == L)? LB : TN; 00998 case LF: 00999 return (face == L)? LT : BF; 01000 case RB: 01001 return (face == R)? RN : BF; 01002 case RT: 01003 return (face == R)? RF : TN; 01004 case RN: 01005 return (face == R)? RT : BN; 01006 case RF: 01007 return (face == R)? RB : TF; 01008 case BN: 01009 return (face == B)? RB : LN; 01010 case BF: 01011 return (face == B)? LB : RF; 01012 case TN: 01013 return (face == T)? LT : RN; 01014 case TF: 01015 return (face == T)? RT : LF; 01016 } 01017 return 0; 01018 } 01019 01020 01021 /* otherface: return face adjoining edge that is not the given face */ 01022 01023 int otherface (int edge, int face) 01024 { 01025 int other = leftface[edge]; 01026 return face == other? rightface[edge] : other; 01027 } 01028 01029 01030 /* makecubetable: create the 256 entry table for cubical polygonization */ 01031 01032 void makecubetable (void) 01033 { 01034 static int isdone= 0; 01035 int i, e, c, done[12], pos[8]; 01036 01037 if(isdone) return; 01038 isdone= 1; 01039 01040 for (i = 0; i < 256; i++) { 01041 for (e = 0; e < 12; e++) done[e] = 0; 01042 for (c = 0; c < 8; c++) pos[c] = MB_BIT(i, c); 01043 for (e = 0; e < 12; e++) 01044 if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) { 01045 INTLIST *ints = NULL; 01046 INTLISTS *lists = (INTLISTS *) MEM_callocN(sizeof(INTLISTS), "mball_intlist"); 01047 int start = e, edge = e; 01048 01049 /* get face that is to right of edge from pos to neg corner: */ 01050 int face = pos[corner1[e]]? rightface[e] : leftface[e]; 01051 01052 while (1) { 01053 edge = nextcwedge(edge, face); 01054 done[edge] = 1; 01055 if (pos[corner1[edge]] != pos[corner2[edge]]) { 01056 INTLIST *tmp = ints; 01057 01058 ints = (INTLIST *) MEM_callocN(sizeof(INTLIST), "mball_intlist"); 01059 ints->i = edge; 01060 ints->next = tmp; /* add edge to head of list */ 01061 01062 if (edge == start) break; 01063 face = otherface(edge, face); 01064 } 01065 } 01066 lists->list = ints; /* add ints to head of table entry */ 01067 lists->next = cubetable[i]; 01068 cubetable[i] = lists; 01069 } 01070 } 01071 } 01072 01073 void BKE_freecubetable(void) 01074 { 01075 int i; 01076 INTLISTS *lists, *nlists; 01077 INTLIST *ints, *nints; 01078 01079 for (i = 0; i < 256; i++) { 01080 lists= cubetable[i]; 01081 while(lists) { 01082 nlists= lists->next; 01083 01084 ints= lists->list; 01085 while(ints) { 01086 nints= ints->next; 01087 MEM_freeN(ints); 01088 ints= nints; 01089 } 01090 01091 MEM_freeN(lists); 01092 lists= nlists; 01093 } 01094 cubetable[i]= NULL; 01095 } 01096 } 01097 01098 /**** Storage ****/ 01099 01100 /* setcenter: set (i,j,k) entry of table[] 01101 * return 1 if already set; otherwise, set and return 0 */ 01102 01103 int setcenter(CENTERLIST *table[], int i, int j, int k) 01104 { 01105 int index; 01106 CENTERLIST *newc, *l, *q; 01107 01108 index= HASH(i, j, k); 01109 q= table[index]; 01110 01111 for (l = q; l != NULL; l = l->next) { 01112 if (l->i == i && l->j == j && l->k == k) return 1; 01113 } 01114 01115 newc = (CENTERLIST *) new_pgn_element(sizeof(CENTERLIST)); 01116 newc->i = i; 01117 newc->j = j; 01118 newc->k = k; 01119 newc->next = q; 01120 table[index] = newc; 01121 01122 return 0; 01123 } 01124 01125 01126 /* setedge: set vertex id for edge */ 01127 01128 void setedge (EDGELIST *table[], 01129 int i1, int j1, 01130 int k1, int i2, 01131 int j2, int k2, 01132 int vid) 01133 { 01134 unsigned int index; 01135 EDGELIST *newe; 01136 01137 if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) { 01138 int t=i1; 01139 i1=i2; 01140 i2=t; 01141 t=j1; 01142 j1=j2; 01143 j2=t; 01144 t=k1; 01145 k1=k2; 01146 k2=t; 01147 } 01148 index = HASH(i1, j1, k1) + HASH(i2, j2, k2); 01149 newe = (EDGELIST *) new_pgn_element(sizeof(EDGELIST)); 01150 newe->i1 = i1; 01151 newe->j1 = j1; 01152 newe->k1 = k1; 01153 newe->i2 = i2; 01154 newe->j2 = j2; 01155 newe->k2 = k2; 01156 newe->vid = vid; 01157 newe->next = table[index]; 01158 table[index] = newe; 01159 } 01160 01161 01162 /* getedge: return vertex id for edge; return -1 if not set */ 01163 01164 int getedge (EDGELIST *table[], 01165 int i1, int j1, int k1, 01166 int i2, int j2, int k2) 01167 { 01168 EDGELIST *q; 01169 01170 if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) { 01171 int t=i1; 01172 i1=i2; 01173 i2=t; 01174 t=j1; 01175 j1=j2; 01176 j2=t; 01177 t=k1; 01178 k1=k2; 01179 k2=t; 01180 } 01181 q = table[HASH(i1, j1, k1)+HASH(i2, j2, k2)]; 01182 for (; q != NULL; q = q->next) 01183 if (q->i1 == i1 && q->j1 == j1 && q->k1 == k1 && 01184 q->i2 == i2 && q->j2 == j2 && q->k2 == k2) 01185 return q->vid; 01186 return -1; 01187 } 01188 01189 01190 /**** Vertices ****/ 01191 01192 #undef R 01193 01194 01195 01196 /* vertid: return index for vertex on edge: 01197 * c1->value and c2->value are presumed of different sign 01198 * return saved index if any; else compute vertex and save */ 01199 01200 /* addtovertices: add v to sequence of vertices */ 01201 01202 void addtovertices (VERTICES *vertices, VERTEX v) 01203 { 01204 if (vertices->count == vertices->max) { 01205 int i; 01206 VERTEX *newv; 01207 vertices->max = vertices->count == 0 ? 10 : 2*vertices->count; 01208 newv = (VERTEX *) MEM_callocN(vertices->max * sizeof(VERTEX), "addtovertices"); 01209 01210 for (i = 0; i < vertices->count; i++) newv[i] = vertices->ptr[i]; 01211 01212 if (vertices->ptr != NULL) MEM_freeN(vertices->ptr); 01213 vertices->ptr = newv; 01214 } 01215 vertices->ptr[vertices->count++] = v; 01216 } 01217 01218 /* vnormal: compute unit length surface normal at point */ 01219 01220 void vnormal (MB_POINT *point, PROCESS *p, MB_POINT *v) 01221 { 01222 float delta= 0.2f*p->delta; 01223 float f = p->function(point->x, point->y, point->z); 01224 01225 v->x = p->function(point->x+delta, point->y, point->z)-f; 01226 v->y = p->function(point->x, point->y+delta, point->z)-f; 01227 v->z = p->function(point->x, point->y, point->z+delta)-f; 01228 f = sqrtf(v->x*v->x + v->y*v->y + v->z*v->z); 01229 01230 if (f != 0.0f) { 01231 v->x /= f; 01232 v->y /= f; 01233 v->z /= f; 01234 } 01235 01236 if(FALSE) { 01237 MB_POINT temp; 01238 01239 delta *= 2.0f; 01240 01241 f = p->function(point->x, point->y, point->z); 01242 01243 temp.x = p->function(point->x+delta, point->y, point->z)-f; 01244 temp.y = p->function(point->x, point->y+delta, point->z)-f; 01245 temp.z = p->function(point->x, point->y, point->z+delta)-f; 01246 f = sqrtf(temp.x*temp.x + temp.y*temp.y + temp.z*temp.z); 01247 01248 if (f != 0.0f) { 01249 temp.x /= f; 01250 temp.y /= f; 01251 temp.z /= f; 01252 01253 v->x+= temp.x; 01254 v->y+= temp.y; 01255 v->z+= temp.z; 01256 01257 f = sqrtf(v->x*v->x + v->y*v->y + v->z*v->z); 01258 01259 if (f != 0.0f) { 01260 v->x /= f; 01261 v->y /= f; 01262 v->z /= f; 01263 } 01264 } 01265 } 01266 01267 } 01268 01269 01270 int vertid (CORNER *c1, CORNER *c2, PROCESS *p, MetaBall *mb) 01271 { 01272 VERTEX v; 01273 MB_POINT a, b; 01274 int vid = getedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k); 01275 01276 if (vid != -1) return vid; /* previously computed */ 01277 a.x = c1->x; 01278 a.y = c1->y; 01279 a.z = c1->z; 01280 b.x = c2->x; 01281 b.y = c2->y; 01282 b.z = c2->z; 01283 01284 converge(&a, &b, c1->value, c2->value, p->function, &v.position, mb, 1); /* position */ 01285 vnormal(&v.position, p, &v.normal); 01286 01287 addtovertices(&p->vertices, v); /* save vertex */ 01288 vid = p->vertices.count-1; 01289 setedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid); 01290 01291 return vid; 01292 } 01293 01294 01295 01296 01297 /* converge: from two points of differing sign, converge to zero crossing */ 01298 /* watch it: p1 and p2 are used to calculate */ 01299 void converge (MB_POINT *p1, MB_POINT *p2, float v1, float v2, 01300 float (*function)(float, float, float), MB_POINT *p, MetaBall *mb, int f) 01301 { 01302 int i = 0; 01303 MB_POINT pos, neg; 01304 float positive = 0.0f, negative = 0.0f; 01305 float dx = 0.0f ,dy = 0.0f ,dz = 0.0f; 01306 01307 if (v1 < 0) { 01308 pos= *p2; 01309 neg= *p1; 01310 positive = v2; 01311 negative = v1; 01312 } 01313 else { 01314 pos= *p1; 01315 neg= *p2; 01316 positive = v1; 01317 negative = v2; 01318 } 01319 01320 dx = pos.x - neg.x; 01321 dy = pos.y - neg.y; 01322 dz = pos.z - neg.z; 01323 01324 /* Approximation by linear interpolation is faster then binary subdivision, 01325 * but it results sometimes (mb->thresh < 0.2) into the strange results */ 01326 if((mb->thresh > 0.2f) && (f==1)){ 01327 if((dy == 0.0f) && (dz == 0.0f)){ 01328 p->x = neg.x - negative*dx/(positive-negative); 01329 p->y = neg.y; 01330 p->z = neg.z; 01331 return; 01332 } 01333 if((dx == 0.0f) && (dz == 0.0f)){ 01334 p->x = neg.x; 01335 p->y = neg.y - negative*dy/(positive-negative); 01336 p->z = neg.z; 01337 return; 01338 } 01339 if((dx == 0.0f) && (dy == 0.0f)){ 01340 p->x = neg.x; 01341 p->y = neg.y; 01342 p->z = neg.z - negative*dz/(positive-negative); 01343 return; 01344 } 01345 } 01346 01347 if((dy == 0.0f) && (dz == 0.0f)){ 01348 p->y = neg.y; 01349 p->z = neg.z; 01350 while (1) { 01351 if (i++ == RES) return; 01352 p->x = 0.5f*(pos.x + neg.x); 01353 if ((function(p->x,p->y,p->z)) > 0.0f) pos.x = p->x; else neg.x = p->x; 01354 } 01355 } 01356 01357 if((dx == 0.0f) && (dz == 0.0f)){ 01358 p->x = neg.x; 01359 p->z = neg.z; 01360 while (1) { 01361 if (i++ == RES) return; 01362 p->y = 0.5f*(pos.y + neg.y); 01363 if ((function(p->x,p->y,p->z)) > 0.0f) pos.y = p->y; else neg.y = p->y; 01364 } 01365 } 01366 01367 if((dx == 0.0f) && (dy == 0.0f)){ 01368 p->x = neg.x; 01369 p->y = neg.y; 01370 while (1) { 01371 if (i++ == RES) return; 01372 p->z = 0.5f*(pos.z + neg.z); 01373 if ((function(p->x,p->y,p->z)) > 0.0f) pos.z = p->z; else neg.z = p->z; 01374 } 01375 } 01376 01377 /* This is necessary to find start point */ 01378 while (1) { 01379 p->x = 0.5f*(pos.x + neg.x); 01380 p->y = 0.5f*(pos.y + neg.y); 01381 p->z = 0.5f*(pos.z + neg.z); 01382 01383 if (i++ == RES) return; 01384 01385 if ((function(p->x, p->y, p->z)) > 0.0f){ 01386 pos.x = p->x; 01387 pos.y = p->y; 01388 pos.z = p->z; 01389 } 01390 else{ 01391 neg.x = p->x; 01392 neg.y = p->y; 01393 neg.z = p->z; 01394 } 01395 } 01396 } 01397 01398 /* ************************************** */ 01399 void add_cube(PROCESS *mbproc, int i, int j, int k, int count) 01400 { 01401 CUBES *ncube; 01402 int n; 01403 int a, b, c; 01404 01405 /* hmmm, not only one, but eight cube will be added on the stack 01406 * ... */ 01407 for(a=i-1; a<i+count; a++) 01408 for(b=j-1; b<j+count; b++) 01409 for(c=k-1; c<k+count; c++) { 01410 /* test if cube has been found before */ 01411 if( setcenter(mbproc->centers, a, b, c)==0 ) { 01412 /* push cube on stack: */ 01413 ncube= (CUBES *) new_pgn_element(sizeof(CUBES)); 01414 ncube->next= mbproc->cubes; 01415 mbproc->cubes= ncube; 01416 01417 ncube->cube.i= a; 01418 ncube->cube.j= b; 01419 ncube->cube.k= c; 01420 01421 /* set corners of initial cube: */ 01422 for (n = 0; n < 8; n++) 01423 ncube->cube.corners[n] = setcorner(mbproc, a+MB_BIT(n,2), b+MB_BIT(n,1), c+MB_BIT(n,0)); 01424 } 01425 } 01426 } 01427 01428 01429 void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) 01430 { 01431 MB_POINT IN, in, OUT, out; /*point;*/ 01432 MetaElem *ml; 01433 int i, j, k, c_i, c_j, c_k; 01434 int index[3]={1,0,-1}; 01435 float f =0.0f; 01436 float in_v /*, out_v*/; 01437 MB_POINT workp; 01438 float tmp_v, workp_v, max_len, len, dx, dy, dz, nx, ny, nz, MAXN; 01439 01440 ml = mainb[a]; 01441 01442 f = 1-(mb->thresh/ml->s); 01443 01444 /* Skip, when Stiffness of MetaElement is too small ... MetaElement can't be 01445 * visible alone ... but still can influence others MetaElements :-) */ 01446 if(f > 0.0f) { 01447 OUT.x = IN.x = in.x= 0.0; 01448 OUT.y = IN.y = in.y= 0.0; 01449 OUT.z = IN.z = in.z= 0.0; 01450 01451 calc_mballco(ml, (float *)&in); 01452 in_v = mbproc->function(in.x, in.y, in.z); 01453 01454 for(i=0;i<3;i++){ 01455 switch (ml->type) { 01456 case MB_BALL: 01457 OUT.x = out.x= IN.x + index[i]*ml->rad; 01458 break; 01459 case MB_TUBE: 01460 case MB_PLANE: 01461 case MB_ELIPSOID: 01462 case MB_CUBE: 01463 OUT.x = out.x= IN.x + index[i]*(ml->expx + ml->rad); 01464 break; 01465 } 01466 01467 for(j=0;j<3;j++) { 01468 switch (ml->type) { 01469 case MB_BALL: 01470 OUT.y = out.y= IN.y + index[j]*ml->rad; 01471 break; 01472 case MB_TUBE: 01473 case MB_PLANE: 01474 case MB_ELIPSOID: 01475 case MB_CUBE: 01476 OUT.y = out.y= IN.y + index[j]*(ml->expy + ml->rad); 01477 break; 01478 } 01479 01480 for(k=0;k<3;k++) { 01481 out.x = OUT.x; 01482 out.y = OUT.y; 01483 switch (ml->type) { 01484 case MB_BALL: 01485 case MB_TUBE: 01486 case MB_PLANE: 01487 out.z= IN.z + index[k]*ml->rad; 01488 break; 01489 case MB_ELIPSOID: 01490 case MB_CUBE: 01491 out.z= IN.z + index[k]*(ml->expz + ml->rad); 01492 break; 01493 } 01494 01495 calc_mballco(ml, (float *)&out); 01496 01497 /*out_v = mbproc->function(out.x, out.y, out.z);*/ /*UNUSED*/ 01498 01499 /* find "first points" on Implicit Surface of MetaElemnt ml */ 01500 workp.x = in.x; 01501 workp.y = in.y; 01502 workp.z = in.z; 01503 workp_v = in_v; 01504 max_len = sqrtf((out.x-in.x)*(out.x-in.x) + (out.y-in.y)*(out.y-in.y) + (out.z-in.z)*(out.z-in.z)); 01505 01506 nx = abs((out.x - in.x)/mbproc->size); 01507 ny = abs((out.y - in.y)/mbproc->size); 01508 nz = abs((out.z - in.z)/mbproc->size); 01509 01510 MAXN = MAX3(nx,ny,nz); 01511 if(MAXN!=0.0f) { 01512 dx = (out.x - in.x)/MAXN; 01513 dy = (out.y - in.y)/MAXN; 01514 dz = (out.z - in.z)/MAXN; 01515 01516 len = 0.0; 01517 while(len<=max_len) { 01518 workp.x += dx; 01519 workp.y += dy; 01520 workp.z += dz; 01521 /* compute value of implicite function */ 01522 tmp_v = mbproc->function(workp.x, workp.y, workp.z); 01523 /* add cube to the stack, when value of implicite function crosses zero value */ 01524 if((tmp_v<0.0f && workp_v>=0.0f)||(tmp_v>0.0f && workp_v<=0.0f)) { 01525 01526 /* indexes of CUBE, which includes "first point" */ 01527 c_i= (int)floor(workp.x/mbproc->size); 01528 c_j= (int)floor(workp.y/mbproc->size); 01529 c_k= (int)floor(workp.z/mbproc->size); 01530 01531 /* add CUBE (with indexes c_i, c_j, c_k) to the stack, 01532 * this cube includes found point of Implicit Surface */ 01533 if (ml->flag & MB_NEGATIVE) 01534 add_cube(mbproc, c_i, c_j, c_k, 2); 01535 else 01536 add_cube(mbproc, c_i, c_j, c_k, 1); 01537 } 01538 len = sqrtf((workp.x-in.x)*(workp.x-in.x) + (workp.y-in.y)*(workp.y-in.y) + (workp.z-in.z)*(workp.z-in.z)); 01539 workp_v = tmp_v; 01540 01541 } 01542 } 01543 } 01544 } 01545 } 01546 } 01547 } 01548 01549 void polygonize(PROCESS *mbproc, MetaBall *mb) 01550 { 01551 CUBE c; 01552 int a; 01553 01554 mbproc->vertices.count = mbproc->vertices.max = 0; 01555 mbproc->vertices.ptr = NULL; 01556 01557 /* allocate hash tables and build cube polygon table: */ 01558 mbproc->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers"); 01559 mbproc->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners"); 01560 mbproc->edges = MEM_callocN(2*HASHSIZE * sizeof(EDGELIST *), "mbproc->edges"); 01561 makecubetable(); 01562 01563 for(a=0; a<totelem; a++) { 01564 01565 /* try to find 8 points on the surface for each MetaElem */ 01566 find_first_points(mbproc, mb, a); 01567 } 01568 01569 /* polygonize all MetaElems of current MetaBall */ 01570 while (mbproc->cubes != NULL) { /* process active cubes till none left */ 01571 c = mbproc->cubes->cube; 01572 01573 /* polygonize the cube directly: */ 01574 docube(&c, mbproc, mb); 01575 01576 /* pop current cube from stack */ 01577 mbproc->cubes = mbproc->cubes->next; 01578 01579 /* test six face directions, maybe add to stack: */ 01580 testface(c.i-1, c.j, c.k, &c, 2, LBN, LBF, LTN, LTF, mbproc); 01581 testface(c.i+1, c.j, c.k, &c, 2, RBN, RBF, RTN, RTF, mbproc); 01582 testface(c.i, c.j-1, c.k, &c, 1, LBN, LBF, RBN, RBF, mbproc); 01583 testface(c.i, c.j+1, c.k, &c, 1, LTN, LTF, RTN, RTF, mbproc); 01584 testface(c.i, c.j, c.k-1, &c, 0, LBN, LTN, RBN, RTN, mbproc); 01585 testface(c.i, c.j, c.k+1, &c, 0, LBF, LTF, RBF, RTF, mbproc); 01586 } 01587 } 01588 01589 float init_meta(Scene *scene, Object *ob) /* return totsize */ 01590 { 01591 Scene *sce_iter= scene; 01592 Base *base; 01593 Object *bob; 01594 MetaBall *mb; 01595 MetaElem *ml; 01596 float size, totsize, obinv[4][4], obmat[4][4], vec[3]; 01597 //float max=0.0; 01598 int a, obnr, zero_size=0; 01599 char obname[MAX_ID_NAME]; 01600 01601 copy_m4_m4(obmat, ob->obmat); /* to cope with duplicators from next_object */ 01602 invert_m4_m4(obinv, ob->obmat); 01603 a= 0; 01604 01605 BLI_split_name_num(obname, &obnr, ob->id.name+2, '.'); 01606 01607 /* make main array */ 01608 next_object(&sce_iter, 0, NULL, NULL); 01609 while(next_object(&sce_iter, 1, &base, &bob)) { 01610 01611 if(bob->type==OB_MBALL) { 01612 zero_size= 0; 01613 ml= NULL; 01614 01615 if(bob==ob && (base->flag & OB_FROMDUPLI)==0) { 01616 mb= ob->data; 01617 01618 if(mb->editelems) ml= mb->editelems->first; 01619 else ml= mb->elems.first; 01620 } 01621 else { 01622 char name[MAX_ID_NAME]; 01623 int nr; 01624 01625 BLI_split_name_num(name, &nr, bob->id.name+2, '.'); 01626 if( strcmp(obname, name)==0 ) { 01627 mb= bob->data; 01628 01629 if(mb->editelems) ml= mb->editelems->first; 01630 else ml= mb->elems.first; 01631 } 01632 } 01633 01634 /* when metaball object has zero scale, then MetaElem to this MetaBall 01635 * will not be put to mainb array */ 01636 if(bob->size[0]==0.0f || bob->size[1]==0.0f || bob->size[2]==0.0f) { 01637 zero_size= 1; 01638 } 01639 else if(bob->parent) { 01640 struct Object *pob=bob->parent; 01641 while(pob) { 01642 if(pob->size[0]==0.0f || pob->size[1]==0.0f || pob->size[2]==0.0f) { 01643 zero_size= 1; 01644 break; 01645 } 01646 pob= pob->parent; 01647 } 01648 } 01649 01650 if (zero_size) { 01651 unsigned int ml_count=0; 01652 while(ml) { 01653 ml_count++; 01654 ml= ml->next; 01655 } 01656 totelem -= ml_count; 01657 } 01658 else { 01659 while(ml) { 01660 if(!(ml->flag & MB_HIDE)) { 01661 int i; 01662 float temp1[4][4], temp2[4][4], temp3[4][4]; 01663 float (*mat)[4] = NULL, (*imat)[4] = NULL; 01664 float max_x, max_y, max_z, min_x, min_y, min_z; 01665 01666 max_x = max_y = max_z = -3.4e38; 01667 min_x = min_y = min_z = 3.4e38; 01668 01669 /* too big stiffness seems only ugly due to linear interpolation 01670 * no need to have possibility for too big stiffness */ 01671 if(ml->s > 10.0f) ml->s = 10.0f; 01672 01673 /* Rotation of MetaElem is stored in quat */ 01674 quat_to_mat4( temp3,ml->quat); 01675 01676 /* Translation of MetaElem */ 01677 unit_m4(temp2); 01678 temp2[3][0]= ml->x; 01679 temp2[3][1]= ml->y; 01680 temp2[3][2]= ml->z; 01681 01682 mult_m4_m4m4(temp1, temp2, temp3); 01683 01684 /* make a copy because of duplicates */ 01685 mainb[a]= new_pgn_element(sizeof(MetaElem)); 01686 *(mainb[a])= *ml; 01687 mainb[a]->bb = new_pgn_element(sizeof(BoundBox)); 01688 01689 mat= new_pgn_element(4*4*sizeof(float)); 01690 imat= new_pgn_element(4*4*sizeof(float)); 01691 01692 /* mat is the matrix to transform from mball into the basis-mball */ 01693 invert_m4_m4(obinv, obmat); 01694 mult_m4_m4m4(temp2, obinv, bob->obmat); 01695 /* MetaBall transformation */ 01696 mult_m4_m4m4(mat, temp2, temp1); 01697 01698 invert_m4_m4(imat,mat); 01699 01700 mainb[a]->rad2= ml->rad*ml->rad; 01701 01702 mainb[a]->mat= (float*) mat; 01703 mainb[a]->imat= (float*) imat; 01704 01705 /* untransformed Bounding Box of MetaElem */ 01706 /* 0 */ 01707 mainb[a]->bb->vec[0][0]= -ml->expx; 01708 mainb[a]->bb->vec[0][1]= -ml->expy; 01709 mainb[a]->bb->vec[0][2]= -ml->expz; 01710 /* 1 */ 01711 mainb[a]->bb->vec[1][0]= ml->expx; 01712 mainb[a]->bb->vec[1][1]= -ml->expy; 01713 mainb[a]->bb->vec[1][2]= -ml->expz; 01714 /* 2 */ 01715 mainb[a]->bb->vec[2][0]= ml->expx; 01716 mainb[a]->bb->vec[2][1]= ml->expy; 01717 mainb[a]->bb->vec[2][2]= -ml->expz; 01718 /* 3 */ 01719 mainb[a]->bb->vec[3][0]= -ml->expx; 01720 mainb[a]->bb->vec[3][1]= ml->expy; 01721 mainb[a]->bb->vec[3][2]= -ml->expz; 01722 /* 4 */ 01723 mainb[a]->bb->vec[4][0]= -ml->expx; 01724 mainb[a]->bb->vec[4][1]= -ml->expy; 01725 mainb[a]->bb->vec[4][2]= ml->expz; 01726 /* 5 */ 01727 mainb[a]->bb->vec[5][0]= ml->expx; 01728 mainb[a]->bb->vec[5][1]= -ml->expy; 01729 mainb[a]->bb->vec[5][2]= ml->expz; 01730 /* 6 */ 01731 mainb[a]->bb->vec[6][0]= ml->expx; 01732 mainb[a]->bb->vec[6][1]= ml->expy; 01733 mainb[a]->bb->vec[6][2]= ml->expz; 01734 /* 7 */ 01735 mainb[a]->bb->vec[7][0]= -ml->expx; 01736 mainb[a]->bb->vec[7][1]= ml->expy; 01737 mainb[a]->bb->vec[7][2]= ml->expz; 01738 01739 /* transformation of Metalem bb */ 01740 for(i=0; i<8; i++) 01741 mul_m4_v3((float ( * )[4])mat, mainb[a]->bb->vec[i]); 01742 01743 /* find max and min of transformed bb */ 01744 for(i=0; i<8; i++){ 01745 /* find maximums */ 01746 if(mainb[a]->bb->vec[i][0] > max_x) max_x = mainb[a]->bb->vec[i][0]; 01747 if(mainb[a]->bb->vec[i][1] > max_y) max_y = mainb[a]->bb->vec[i][1]; 01748 if(mainb[a]->bb->vec[i][2] > max_z) max_z = mainb[a]->bb->vec[i][2]; 01749 /* find minimums */ 01750 if(mainb[a]->bb->vec[i][0] < min_x) min_x = mainb[a]->bb->vec[i][0]; 01751 if(mainb[a]->bb->vec[i][1] < min_y) min_y = mainb[a]->bb->vec[i][1]; 01752 if(mainb[a]->bb->vec[i][2] < min_z) min_z = mainb[a]->bb->vec[i][2]; 01753 } 01754 01755 /* create "new" bb, only point 0 and 6, which are 01756 * neccesary for octal tree filling */ 01757 mainb[a]->bb->vec[0][0] = min_x - ml->rad; 01758 mainb[a]->bb->vec[0][1] = min_y - ml->rad; 01759 mainb[a]->bb->vec[0][2] = min_z - ml->rad; 01760 01761 mainb[a]->bb->vec[6][0] = max_x + ml->rad; 01762 mainb[a]->bb->vec[6][1] = max_y + ml->rad; 01763 mainb[a]->bb->vec[6][2] = max_z + ml->rad; 01764 01765 a++; 01766 } 01767 ml= ml->next; 01768 } 01769 } 01770 } 01771 } 01772 01773 01774 /* totsize (= 'manhattan' radius) */ 01775 totsize= 0.0; 01776 for(a=0; a<totelem; a++) { 01777 01778 vec[0]= mainb[a]->x + mainb[a]->rad + mainb[a]->expx; 01779 vec[1]= mainb[a]->y + mainb[a]->rad + mainb[a]->expy; 01780 vec[2]= mainb[a]->z + mainb[a]->rad + mainb[a]->expz; 01781 01782 calc_mballco(mainb[a], vec); 01783 01784 size= fabsf( vec[0] ); 01785 if( size > totsize ) totsize= size; 01786 size= fabsf( vec[1] ); 01787 if( size > totsize ) totsize= size; 01788 size= fabsf( vec[2] ); 01789 if( size > totsize ) totsize= size; 01790 01791 vec[0]= mainb[a]->x - mainb[a]->rad; 01792 vec[1]= mainb[a]->y - mainb[a]->rad; 01793 vec[2]= mainb[a]->z - mainb[a]->rad; 01794 01795 calc_mballco(mainb[a], vec); 01796 01797 size= fabsf( vec[0] ); 01798 if( size > totsize ) totsize= size; 01799 size= fabsf( vec[1] ); 01800 if( size > totsize ) totsize= size; 01801 size= fabsf( vec[2] ); 01802 if( size > totsize ) totsize= size; 01803 } 01804 01805 for(a=0; a<totelem; a++) { 01806 thresh+= densfunc( mainb[a], 2.0f*totsize, 2.0f*totsize, 2.0f*totsize); 01807 } 01808 01809 return totsize; 01810 } 01811 01812 /* if MetaElem lies in node, then node includes MetaElem pointer (ml_p) 01813 * pointing at MetaElem (ml) 01814 */ 01815 void fill_metaball_octal_node(octal_node *node, MetaElem *ml, short i) 01816 { 01817 ml_pointer *ml_p; 01818 01819 ml_p= MEM_mallocN(sizeof(ml_pointer), "ml_pointer"); 01820 ml_p->ml= ml; 01821 BLI_addtail(&(node->nodes[i]->elems), ml_p); 01822 node->count++; 01823 01824 if(ml->flag & MB_NEGATIVE) { 01825 node->nodes[i]->neg++; 01826 } 01827 else{ 01828 node->nodes[i]->pos++; 01829 } 01830 } 01831 01832 /* Node is subdivided as is ilustrated on the following figure: 01833 * 01834 * +------+------+ 01835 * / / /| 01836 * +------+------+ | 01837 * / / /| + 01838 * +------+------+ |/| 01839 * | | | + | 01840 * | | |/| + 01841 * +------+------+ |/ 01842 * | | | + 01843 * | | |/ 01844 * +------+------+ 01845 * 01846 */ 01847 void subdivide_metaball_octal_node(octal_node *node, float size_x, float size_y, float size_z, short depth) 01848 { 01849 MetaElem *ml; 01850 ml_pointer *ml_p; 01851 float x,y,z; 01852 int a,i; 01853 01854 /* create new nodes */ 01855 for(a=0;a<8;a++){ 01856 node->nodes[a]= MEM_mallocN(sizeof(octal_node),"octal_node"); 01857 for(i=0;i<8;i++) 01858 node->nodes[a]->nodes[i]= NULL; 01859 node->nodes[a]->parent= node; 01860 node->nodes[a]->elems.first= NULL; 01861 node->nodes[a]->elems.last= NULL; 01862 node->nodes[a]->count= 0; 01863 node->nodes[a]->neg= 0; 01864 node->nodes[a]->pos= 0; 01865 } 01866 01867 size_x /= 2; 01868 size_y /= 2; 01869 size_z /= 2; 01870 01871 /* center of node */ 01872 node->x = x = node->x_min + size_x; 01873 node->y = y = node->y_min + size_y; 01874 node->z = z = node->z_min + size_z; 01875 01876 /* setting up of border points of new nodes */ 01877 node->nodes[0]->x_min = node->x_min; 01878 node->nodes[0]->y_min = node->y_min; 01879 node->nodes[0]->z_min = node->z_min; 01880 node->nodes[0]->x = node->nodes[0]->x_min + size_x/2; 01881 node->nodes[0]->y = node->nodes[0]->y_min + size_y/2; 01882 node->nodes[0]->z = node->nodes[0]->z_min + size_z/2; 01883 01884 node->nodes[1]->x_min = x; 01885 node->nodes[1]->y_min = node->y_min; 01886 node->nodes[1]->z_min = node->z_min; 01887 node->nodes[1]->x = node->nodes[1]->x_min + size_x/2; 01888 node->nodes[1]->y = node->nodes[1]->y_min + size_y/2; 01889 node->nodes[1]->z = node->nodes[1]->z_min + size_z/2; 01890 01891 node->nodes[2]->x_min = x; 01892 node->nodes[2]->y_min = y; 01893 node->nodes[2]->z_min = node->z_min; 01894 node->nodes[2]->x = node->nodes[2]->x_min + size_x/2; 01895 node->nodes[2]->y = node->nodes[2]->y_min + size_y/2; 01896 node->nodes[2]->z = node->nodes[2]->z_min + size_z/2; 01897 01898 node->nodes[3]->x_min = node->x_min; 01899 node->nodes[3]->y_min = y; 01900 node->nodes[3]->z_min = node->z_min; 01901 node->nodes[3]->x = node->nodes[3]->x_min + size_x/2; 01902 node->nodes[3]->y = node->nodes[3]->y_min + size_y/2; 01903 node->nodes[3]->z = node->nodes[3]->z_min + size_z/2; 01904 01905 node->nodes[4]->x_min = node->x_min; 01906 node->nodes[4]->y_min = node->y_min; 01907 node->nodes[4]->z_min = z; 01908 node->nodes[4]->x = node->nodes[4]->x_min + size_x/2; 01909 node->nodes[4]->y = node->nodes[4]->y_min + size_y/2; 01910 node->nodes[4]->z = node->nodes[4]->z_min + size_z/2; 01911 01912 node->nodes[5]->x_min = x; 01913 node->nodes[5]->y_min = node->y_min; 01914 node->nodes[5]->z_min = z; 01915 node->nodes[5]->x = node->nodes[5]->x_min + size_x/2; 01916 node->nodes[5]->y = node->nodes[5]->y_min + size_y/2; 01917 node->nodes[5]->z = node->nodes[5]->z_min + size_z/2; 01918 01919 node->nodes[6]->x_min = x; 01920 node->nodes[6]->y_min = y; 01921 node->nodes[6]->z_min = z; 01922 node->nodes[6]->x = node->nodes[6]->x_min + size_x/2; 01923 node->nodes[6]->y = node->nodes[6]->y_min + size_y/2; 01924 node->nodes[6]->z = node->nodes[6]->z_min + size_z/2; 01925 01926 node->nodes[7]->x_min = node->x_min; 01927 node->nodes[7]->y_min = y; 01928 node->nodes[7]->z_min = z; 01929 node->nodes[7]->x = node->nodes[7]->x_min + size_x/2; 01930 node->nodes[7]->y = node->nodes[7]->y_min + size_y/2; 01931 node->nodes[7]->z = node->nodes[7]->z_min + size_z/2; 01932 01933 ml_p= node->elems.first; 01934 01935 /* setting up references of MetaElems for new nodes */ 01936 while(ml_p){ 01937 ml= ml_p->ml; 01938 if(ml->bb->vec[0][2] < z){ 01939 if(ml->bb->vec[0][1] < y){ 01940 /* vec[0][0] lies in first octant */ 01941 if(ml->bb->vec[0][0] < x){ 01942 /* ml belongs to the (0)1st node */ 01943 fill_metaball_octal_node(node, ml, 0); 01944 01945 /* ml belongs to the (3)4th node */ 01946 if(ml->bb->vec[6][1] >= y){ 01947 fill_metaball_octal_node(node, ml, 3); 01948 01949 /* ml belongs to the (7)8th node */ 01950 if(ml->bb->vec[6][2] >= z){ 01951 fill_metaball_octal_node(node, ml, 7); 01952 } 01953 } 01954 01955 /* ml belongs to the (1)2nd node */ 01956 if(ml->bb->vec[6][0] >= x){ 01957 fill_metaball_octal_node(node, ml, 1); 01958 01959 /* ml belongs to the (5)6th node */ 01960 if(ml->bb->vec[6][2] >= z){ 01961 fill_metaball_octal_node(node, ml, 5); 01962 } 01963 } 01964 01965 /* ml belongs to the (2)3th node */ 01966 if((ml->bb->vec[6][0] >= x) && (ml->bb->vec[6][1] >= y)){ 01967 fill_metaball_octal_node(node, ml, 2); 01968 01969 /* ml belong to the (6)7th node */ 01970 if(ml->bb->vec[6][2] >= z){ 01971 fill_metaball_octal_node(node, ml, 6); 01972 } 01973 01974 } 01975 01976 /* ml belongs to the (4)5th node too */ 01977 if(ml->bb->vec[6][2] >= z){ 01978 fill_metaball_octal_node(node, ml, 4); 01979 } 01980 01981 01982 01983 } 01984 /* vec[0][0] is in the (1)second octant */ 01985 else{ 01986 /* ml belong to the (1)2nd node */ 01987 fill_metaball_octal_node(node, ml, 1); 01988 01989 /* ml belongs to the (2)3th node */ 01990 if(ml->bb->vec[6][1] >= y){ 01991 fill_metaball_octal_node(node, ml, 2); 01992 01993 /* ml belongs to the (6)7th node */ 01994 if(ml->bb->vec[6][2] >= z){ 01995 fill_metaball_octal_node(node, ml, 6); 01996 } 01997 01998 } 01999 02000 /* ml belongs to the (5)6th node */ 02001 if(ml->bb->vec[6][2] >= z){ 02002 fill_metaball_octal_node(node, ml, 5); 02003 } 02004 } 02005 } 02006 else{ 02007 /* vec[0][0] is in the (3)4th octant */ 02008 if(ml->bb->vec[0][0] < x){ 02009 /* ml belongs to the (3)4nd node */ 02010 fill_metaball_octal_node(node, ml, 3); 02011 02012 /* ml belongs to the (7)8th node */ 02013 if(ml->bb->vec[6][2] >= z){ 02014 fill_metaball_octal_node(node, ml, 7); 02015 } 02016 02017 02018 /* ml belongs to the (2)3th node */ 02019 if(ml->bb->vec[6][0] >= x){ 02020 fill_metaball_octal_node(node, ml, 2); 02021 02022 /* ml belongs to the (6)7th node */ 02023 if(ml->bb->vec[6][2] >= z){ 02024 fill_metaball_octal_node(node, ml, 6); 02025 } 02026 } 02027 } 02028 02029 } 02030 02031 /* vec[0][0] is in the (2)3th octant */ 02032 if((ml->bb->vec[0][0] >= x) && (ml->bb->vec[0][1] >= y)){ 02033 /* ml belongs to the (2)3th node */ 02034 fill_metaball_octal_node(node, ml, 2); 02035 02036 /* ml belongs to the (6)7th node */ 02037 if(ml->bb->vec[6][2] >= z){ 02038 fill_metaball_octal_node(node, ml, 6); 02039 } 02040 } 02041 } 02042 else{ 02043 if(ml->bb->vec[0][1] < y){ 02044 /* vec[0][0] lies in (4)5th octant */ 02045 if(ml->bb->vec[0][0] < x){ 02046 /* ml belongs to the (4)5th node */ 02047 fill_metaball_octal_node(node, ml, 4); 02048 02049 if(ml->bb->vec[6][0] >= x){ 02050 fill_metaball_octal_node(node, ml, 5); 02051 } 02052 02053 if(ml->bb->vec[6][1] >= y){ 02054 fill_metaball_octal_node(node, ml, 7); 02055 } 02056 02057 if((ml->bb->vec[6][0] >= x) && (ml->bb->vec[6][1] >= y)){ 02058 fill_metaball_octal_node(node, ml, 6); 02059 } 02060 } 02061 /* vec[0][0] lies in (5)6th octant */ 02062 else{ 02063 fill_metaball_octal_node(node, ml, 5); 02064 02065 if(ml->bb->vec[6][1] >= y){ 02066 fill_metaball_octal_node(node, ml, 6); 02067 } 02068 } 02069 } 02070 else{ 02071 /* vec[0][0] lies in (7)8th octant */ 02072 if(ml->bb->vec[0][0] < x){ 02073 fill_metaball_octal_node(node, ml, 7); 02074 02075 if(ml->bb->vec[6][0] >= x){ 02076 fill_metaball_octal_node(node, ml, 6); 02077 } 02078 } 02079 02080 } 02081 02082 /* vec[0][0] lies in (6)7th octant */ 02083 if((ml->bb->vec[0][0] >= x) && (ml->bb->vec[0][1] >= y)){ 02084 fill_metaball_octal_node(node, ml, 6); 02085 } 02086 } 02087 ml_p= ml_p->next; 02088 } 02089 02090 /* free references of MetaElems for curent node (it is not needed anymore) */ 02091 BLI_freelistN(&node->elems); 02092 02093 depth--; 02094 02095 if(depth>0){ 02096 for(a=0;a<8;a++){ 02097 if(node->nodes[a]->count > 0) /* if node is not empty, then it is subdivided */ 02098 subdivide_metaball_octal_node(node->nodes[a], size_x, size_y, size_z, depth); 02099 } 02100 } 02101 } 02102 02103 /* free all octal nodes recursively */ 02104 void free_metaball_octal_node(octal_node *node) 02105 { 02106 int a; 02107 for(a=0;a<8;a++){ 02108 if(node->nodes[a]!=NULL) free_metaball_octal_node(node->nodes[a]); 02109 } 02110 BLI_freelistN(&node->elems); 02111 MEM_freeN(node); 02112 } 02113 02114 /* If scene include more then one MetaElem, then octree is used */ 02115 void init_metaball_octal_tree(int depth) 02116 { 02117 struct octal_node *node; 02118 ml_pointer *ml_p; 02119 float size[3]; 02120 int a; 02121 02122 metaball_tree= MEM_mallocN(sizeof(octal_tree), "metaball_octal_tree"); 02123 metaball_tree->first= node= MEM_mallocN(sizeof(octal_node), "metaball_octal_node"); 02124 /* maximal depth of octree */ 02125 metaball_tree->depth= depth; 02126 02127 metaball_tree->neg= node->neg=0; 02128 metaball_tree->pos= node->pos=0; 02129 02130 node->elems.first= NULL; 02131 node->elems.last= NULL; 02132 node->count=0; 02133 02134 for(a=0;a<8;a++) 02135 node->nodes[a]=NULL; 02136 02137 node->x_min= node->y_min= node->z_min= FLT_MAX; 02138 node->x_max= node->y_max= node->z_max= -FLT_MAX; 02139 02140 /* size of octal tree scene */ 02141 for(a=0;a<totelem;a++) { 02142 if(mainb[a]->bb->vec[0][0] < node->x_min) node->x_min= mainb[a]->bb->vec[0][0]; 02143 if(mainb[a]->bb->vec[0][1] < node->y_min) node->y_min= mainb[a]->bb->vec[0][1]; 02144 if(mainb[a]->bb->vec[0][2] < node->z_min) node->z_min= mainb[a]->bb->vec[0][2]; 02145 02146 if(mainb[a]->bb->vec[6][0] > node->x_max) node->x_max= mainb[a]->bb->vec[6][0]; 02147 if(mainb[a]->bb->vec[6][1] > node->y_max) node->y_max= mainb[a]->bb->vec[6][1]; 02148 if(mainb[a]->bb->vec[6][2] > node->z_max) node->z_max= mainb[a]->bb->vec[6][2]; 02149 02150 ml_p= MEM_mallocN(sizeof(ml_pointer), "ml_pointer"); 02151 ml_p->ml= mainb[a]; 02152 BLI_addtail(&node->elems, ml_p); 02153 02154 if(mainb[a]->flag & MB_NEGATIVE) { 02155 /* number of negative MetaElem in scene */ 02156 metaball_tree->neg++; 02157 } 02158 else{ 02159 /* number of positive MetaElem in scene */ 02160 metaball_tree->pos++; 02161 } 02162 } 02163 02164 /* size of first node */ 02165 size[0]= node->x_max - node->x_min; 02166 size[1]= node->y_max - node->y_min; 02167 size[2]= node->z_max - node->z_min; 02168 02169 /* first node is subdivided recursively */ 02170 subdivide_metaball_octal_node(node, size[0], size[1], size[2], metaball_tree->depth); 02171 } 02172 02173 void metaball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) 02174 { 02175 PROCESS mbproc; 02176 MetaBall *mb; 02177 DispList *dl; 02178 int a, nr_cubes; 02179 float *ve, *no, totsize, width; 02180 02181 mb= ob->data; 02182 02183 if(totelem==0) return; 02184 if(!(G.rendering) && (mb->flag==MB_UPDATE_NEVER)) return; 02185 if(G.moving && mb->flag==MB_UPDATE_FAST) return; 02186 02187 curindex= totindex= 0; 02188 indices= NULL; 02189 thresh= mb->thresh; 02190 02191 /* total number of MetaElems (totelem) is precomputed in find_basis_mball() function */ 02192 mainb= MEM_mallocN(sizeof(void *)*totelem, "mainb"); 02193 02194 /* initialize all mainb (MetaElems) */ 02195 totsize= init_meta(scene, ob); 02196 02197 if(metaball_tree){ 02198 free_metaball_octal_node(metaball_tree->first); 02199 MEM_freeN(metaball_tree); 02200 metaball_tree= NULL; 02201 } 02202 02203 /* if scene includes more then one MetaElem, then octal tree optimalisation is used */ 02204 if((totelem > 1) && (totelem <= 64)) init_metaball_octal_tree(1); 02205 if((totelem > 64) && (totelem <= 128)) init_metaball_octal_tree(2); 02206 if((totelem > 128) && (totelem <= 512)) init_metaball_octal_tree(3); 02207 if((totelem > 512) && (totelem <= 1024)) init_metaball_octal_tree(4); 02208 if(totelem > 1024) init_metaball_octal_tree(5); 02209 02210 /* don't polygonize metaballs with too high resolution (base mball to small) 02211 * note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */ 02212 if(metaball_tree) { 02213 if( ob->size[0] <= 0.00001f * (metaball_tree->first->x_max - metaball_tree->first->x_min) || 02214 ob->size[1] <= 0.00001f * (metaball_tree->first->y_max - metaball_tree->first->y_min) || 02215 ob->size[2] <= 0.00001f * (metaball_tree->first->z_max - metaball_tree->first->z_min)) 02216 { 02217 new_pgn_element(-1); /* free values created by init_meta */ 02218 02219 MEM_freeN(mainb); 02220 02221 /* free tree */ 02222 free_metaball_octal_node(metaball_tree->first); 02223 MEM_freeN(metaball_tree); 02224 metaball_tree= NULL; 02225 02226 return; 02227 } 02228 } 02229 02230 /* width is size per polygonize cube */ 02231 if(G.rendering) width= mb->rendersize; 02232 else { 02233 width= mb->wiresize; 02234 if(G.moving && mb->flag==MB_UPDATE_HALFRES) width*= 2; 02235 } 02236 /* nr_cubes is just for safety, minimum is totsize */ 02237 nr_cubes= (int)(0.5f+totsize/width); 02238 02239 /* init process */ 02240 mbproc.function = metaball; 02241 mbproc.size = width; 02242 mbproc.bounds = nr_cubes; 02243 mbproc.cubes= NULL; 02244 mbproc.delta = width/(float)(RES*RES); 02245 02246 polygonize(&mbproc, mb); 02247 02248 MEM_freeN(mainb); 02249 02250 /* free octal tree */ 02251 if(totelem > 1){ 02252 free_metaball_octal_node(metaball_tree->first); 02253 MEM_freeN(metaball_tree); 02254 metaball_tree= NULL; 02255 } 02256 02257 if(curindex) { 02258 dl= MEM_callocN(sizeof(DispList), "mbaldisp"); 02259 BLI_addtail(dispbase, dl); 02260 dl->type= DL_INDEX4; 02261 dl->nr= mbproc.vertices.count; 02262 dl->parts= curindex; 02263 02264 dl->index= indices; 02265 indices= NULL; 02266 02267 a= mbproc.vertices.count; 02268 dl->verts= ve= MEM_mallocN(sizeof(float)*3*a, "mballverts"); 02269 dl->nors= no= MEM_mallocN(sizeof(float)*3*a, "mballnors"); 02270 02271 for(a=0; a<mbproc.vertices.count; a++, no+=3, ve+=3) { 02272 ve[0]= mbproc.vertices.ptr[a].position.x; 02273 ve[1]= mbproc.vertices.ptr[a].position.y; 02274 ve[2]= mbproc.vertices.ptr[a].position.z; 02275 02276 no[0]= mbproc.vertices.ptr[a].normal.x; 02277 no[1]= mbproc.vertices.ptr[a].normal.y; 02278 no[2]= mbproc.vertices.ptr[a].normal.z; 02279 } 02280 } 02281 02282 freepolygonize(&mbproc); 02283 } 02284