2011-10-10 09:38:02 +00:00
|
|
|
/*
|
2008-01-07 19:13:47 +00:00
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
2008-01-07 19:13:47 +00:00
|
|
|
* of the License, or (at your option) any later version.
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
2003-12-08 13:30:04 +00:00
|
|
|
* Contributor(s): Jiri Hnidek <jiri.hnidek@vslib.cz>.
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
2008-01-07 19:13:47 +00:00
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
2011-10-10 09:38:02 +00:00
|
|
|
*
|
|
|
|
* MetaBalls are created from a single Object (with a name without number in it),
|
|
|
|
* here the DispList and BoundBox also is located.
|
|
|
|
* All objects with the same name (but with a number in it) are added to this.
|
|
|
|
*
|
|
|
|
* texture coordinates are patched within the displist
|
2002-10-12 11:37:38 +00:00
|
|
|
*/
|
|
|
|
|
2011-02-27 20:40:57 +00:00
|
|
|
/** \file blender/blenkernel/intern/mball.c
|
|
|
|
* \ingroup bke
|
|
|
|
*/
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <stdlib.h>
|
2003-12-08 13:48:20 +00:00
|
|
|
#include <ctype.h>
|
2007-04-20 12:56:51 +00:00
|
|
|
#include <float.h>
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "DNA_material_types.h"
|
|
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "DNA_meta_types.h"
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
2009-11-10 20:43:45 +00:00
|
|
|
#include "BLI_math.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2011-10-27 05:34:39 +00:00
|
|
|
#include "BLI_bpath.h"
|
2011-01-07 19:18:31 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
#include "BKE_global.h"
|
|
|
|
#include "BKE_main.h"
|
|
|
|
|
|
|
|
/* #include "BKE_object.h" */
|
2009-08-03 13:09:23 +00:00
|
|
|
#include "BKE_animsys.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "BKE_scene.h"
|
|
|
|
#include "BKE_library.h"
|
|
|
|
#include "BKE_displist.h"
|
|
|
|
#include "BKE_mball.h"
|
2005-07-18 19:59:51 +00:00
|
|
|
#include "BKE_object.h"
|
2011-04-26 07:17:21 +00:00
|
|
|
#include "BKE_material.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2004-11-10 13:20:13 +00:00
|
|
|
/* Global variables */
|
|
|
|
|
2009-08-03 14:40:10 +00:00
|
|
|
static float thresh= 0.6f;
|
|
|
|
static int totelem=0;
|
|
|
|
static MetaElem **mainb;
|
|
|
|
static octal_tree *metaball_tree = NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
/* Functions */
|
|
|
|
|
|
|
|
void unlink_mball(MetaBall *mb)
|
|
|
|
{
|
|
|
|
int a;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (a=0; a<mb->totcol; a++) {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mb->mat[a]) mb->mat[a]->id.us--;
|
2011-02-13 10:52:18 +00:00
|
|
|
mb->mat[a]= NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-26 13:07:59 +00:00
|
|
|
/* do not free mball itself */
|
2002-10-12 11:37:38 +00:00
|
|
|
void free_mball(MetaBall *mb)
|
|
|
|
{
|
|
|
|
unlink_mball(mb);
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mb->adt) {
|
2010-12-13 06:31:49 +00:00
|
|
|
BKE_free_animdata((ID *)mb);
|
|
|
|
mb->adt = NULL;
|
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mb->mat) MEM_freeN(mb->mat);
|
|
|
|
if (mb->bb) MEM_freeN(mb->bb);
|
2002-10-12 11:37:38 +00:00
|
|
|
BLI_freelistN(&mb->elems);
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mb->disp.first) freedisplist(&mb->disp);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2010-11-17 09:45:45 +00:00
|
|
|
MetaBall *add_mball(const char *name)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
MetaBall *mb;
|
|
|
|
|
2007-03-11 16:25:17 +00:00
|
|
|
mb= alloc_libblock(&G.main->mball, ID_MB, name);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
mb->size[0]= mb->size[1]= mb->size[2]= 1.0;
|
2004-03-14 16:59:48 +00:00
|
|
|
mb->texflag= MB_AUTOSPACE;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
mb->wiresize= 0.4f;
|
|
|
|
mb->rendersize= 0.2f;
|
|
|
|
mb->thresh= 0.6f;
|
|
|
|
|
|
|
|
return mb;
|
|
|
|
}
|
|
|
|
|
|
|
|
MetaBall *copy_mball(MetaBall *mb)
|
|
|
|
{
|
|
|
|
MetaBall *mbn;
|
|
|
|
int a;
|
|
|
|
|
2011-11-07 04:36:37 +00:00
|
|
|
mbn= copy_libblock(&mb->id);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2008-01-01 18:29:19 +00:00
|
|
|
BLI_duplicatelist(&mbn->elems, &mb->elems);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
mbn->mat= MEM_dupallocN(mb->mat);
|
2012-03-24 06:18:31 +00:00
|
|
|
for (a=0; a<mbn->totcol; a++) {
|
2002-10-12 11:37:38 +00:00
|
|
|
id_us_plus((ID *)mbn->mat[a]);
|
|
|
|
}
|
|
|
|
mbn->bb= MEM_dupallocN(mb->bb);
|
2011-04-21 09:38:09 +00:00
|
|
|
|
|
|
|
mbn->editelems= NULL;
|
|
|
|
mbn->lastelem= NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
return mbn;
|
|
|
|
}
|
|
|
|
|
2011-04-26 07:17:21 +00:00
|
|
|
static void extern_local_mball(MetaBall *mb)
|
|
|
|
{
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mb->mat) {
|
2011-04-26 07:17:21 +00:00
|
|
|
extern_local_matarar(mb->mat, mb->totcol);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
void make_local_mball(MetaBall *mb)
|
|
|
|
{
|
2011-04-26 07:17:21 +00:00
|
|
|
Main *bmain= G.main;
|
2002-10-12 11:37:38 +00:00
|
|
|
Object *ob;
|
2011-10-27 05:34:39 +00:00
|
|
|
int is_local= FALSE, is_lib= FALSE;
|
2003-04-26 13:07:59 +00:00
|
|
|
|
|
|
|
/* - only lib users: do nothing
|
|
|
|
* - only local users: set flag
|
|
|
|
* - mixed: make copy
|
2002-10-12 11:37:38 +00:00
|
|
|
*/
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mb->id.lib==NULL) return;
|
|
|
|
if (mb->id.us==1) {
|
2011-10-27 05:34:39 +00:00
|
|
|
id_clear_lib_data(bmain, &mb->id);
|
2011-04-26 07:17:21 +00:00
|
|
|
extern_local_mball(mb);
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
return;
|
|
|
|
}
|
2011-04-26 07:17:21 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (ob= G.main->object.first; ob && ELEM(0, is_lib, is_local); ob= ob->id.next) {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ob->data == mb) {
|
|
|
|
if (ob->id.lib) is_lib= TRUE;
|
2011-10-27 05:34:39 +00:00
|
|
|
else is_local= TRUE;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (is_local && is_lib == FALSE) {
|
2011-10-27 05:34:39 +00:00
|
|
|
id_clear_lib_data(bmain, &mb->id);
|
2011-04-26 07:17:21 +00:00
|
|
|
extern_local_mball(mb);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
else if (is_local && is_lib) {
|
2011-11-30 00:32:13 +00:00
|
|
|
MetaBall *mb_new= copy_mball(mb);
|
|
|
|
mb_new->id.us= 0;
|
2011-04-26 07:17:21 +00:00
|
|
|
|
2011-10-27 05:34:39 +00:00
|
|
|
/* Remap paths of new ID using old library as base. */
|
2011-11-30 00:32:13 +00:00
|
|
|
BKE_id_lib_local_paths(bmain, mb->id.lib, &mb_new->id);
|
2011-10-27 05:34:39 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (ob= G.main->object.first; ob; ob= ob->id.next) {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ob->data == mb) {
|
|
|
|
if (ob->id.lib==NULL) {
|
2011-11-30 00:32:13 +00:00
|
|
|
ob->data= mb_new;
|
|
|
|
mb_new->id.us++;
|
2002-10-12 11:37:38 +00:00
|
|
|
mb->id.us--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-08-23 00:57:19 +00:00
|
|
|
|
|
|
|
/* most simple meta-element adding function
|
2011-04-21 05:49:47 +00:00
|
|
|
* don't do context manipulation here (rna uses) */
|
2010-08-23 00:57:19 +00:00
|
|
|
MetaElem *add_metaball_element(MetaBall *mb, const int type)
|
|
|
|
{
|
|
|
|
MetaElem *ml= MEM_callocN(sizeof(MetaElem), "metaelem");
|
|
|
|
|
|
|
|
unit_qt(ml->quat);
|
|
|
|
|
|
|
|
ml->rad= 2.0;
|
|
|
|
ml->s= 2.0;
|
|
|
|
ml->flag= MB_SCALE_RAD;
|
|
|
|
|
|
|
|
switch(type) {
|
|
|
|
case MB_BALL:
|
|
|
|
ml->type = MB_BALL;
|
|
|
|
ml->expx= ml->expy= ml->expz= 1.0;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case MB_TUBE:
|
|
|
|
ml->type = MB_TUBE;
|
|
|
|
ml->expx= ml->expy= ml->expz= 1.0;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case MB_PLANE:
|
|
|
|
ml->type = MB_PLANE;
|
|
|
|
ml->expx= ml->expy= ml->expz= 1.0;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case MB_ELIPSOID:
|
|
|
|
ml->type = MB_ELIPSOID;
|
|
|
|
ml->expx= 1.2f;
|
|
|
|
ml->expy= 0.8f;
|
|
|
|
ml->expz= 1.0;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case MB_CUBE:
|
|
|
|
ml->type = MB_CUBE;
|
|
|
|
ml->expx= ml->expy= ml->expz= 1.0;
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_addtail(&mb->elems, ml);
|
|
|
|
|
|
|
|
return ml;
|
|
|
|
}
|
2003-12-08 13:30:04 +00:00
|
|
|
/** Compute bounding box of all MetaElems/MetaBalls.
|
|
|
|
*
|
|
|
|
* Bounding box is computed from polygonized surface. Object *ob is
|
2011-04-21 05:49:47 +00:00
|
|
|
* basic MetaBall (usually with name Meta). All other MetaBalls (with
|
2003-12-08 13:30:04 +00:00
|
|
|
* names Meta.001, Meta.002, etc) are included in this Bounding Box.
|
|
|
|
*/
|
2002-10-12 11:37:38 +00:00
|
|
|
void tex_space_mball(Object *ob)
|
|
|
|
{
|
|
|
|
DispList *dl;
|
|
|
|
BoundBox *bb;
|
2011-04-21 05:49:47 +00:00
|
|
|
float *data, min[3], max[3] /*, loc[3], size[3] */;
|
2002-10-12 11:37:38 +00:00
|
|
|
int tot, doit=0;
|
2003-09-05 13:54:22 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ob->bb==NULL) ob->bb= MEM_callocN(sizeof(BoundBox), "mb boundbox");
|
2002-10-12 11:37:38 +00:00
|
|
|
bb= ob->bb;
|
|
|
|
|
|
|
|
/* Weird one, this. */
|
|
|
|
/* INIT_MINMAX(min, max); */
|
|
|
|
(min)[0]= (min)[1]= (min)[2]= 1.0e30f;
|
|
|
|
(max)[0]= (max)[1]= (max)[2]= -1.0e30f;
|
|
|
|
|
|
|
|
dl= ob->disp.first;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (dl) {
|
2002-10-12 11:37:38 +00:00
|
|
|
tot= dl->nr;
|
2012-02-23 02:17:50 +00:00
|
|
|
if (tot) doit= 1;
|
2002-10-12 11:37:38 +00:00
|
|
|
data= dl->verts;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (tot--) {
|
2002-10-12 11:37:38 +00:00
|
|
|
/* Also weird... but longer. From utildefines. */
|
|
|
|
DO_MINMAX(data, min, max);
|
|
|
|
data+= 3;
|
|
|
|
}
|
|
|
|
dl= dl->next;
|
|
|
|
}
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (!doit) {
|
2005-07-18 17:33:51 +00:00
|
|
|
min[0] = min[1] = min[2] = -1.0f;
|
|
|
|
max[0] = max[1] = max[2] = 1.0f;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-03-03 20:19:11 +00:00
|
|
|
#if 0
|
2005-07-18 17:33:51 +00:00
|
|
|
loc[0]= (min[0]+max[0])/2.0f;
|
|
|
|
loc[1]= (min[1]+max[1])/2.0f;
|
|
|
|
loc[2]= (min[2]+max[2])/2.0f;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2005-07-18 17:33:51 +00:00
|
|
|
size[0]= (max[0]-min[0])/2.0f;
|
|
|
|
size[1]= (max[1]-min[1])/2.0f;
|
|
|
|
size[2]= (max[2]-min[2])/2.0f;
|
2012-03-03 20:19:11 +00:00
|
|
|
#endif
|
2005-07-18 17:33:51 +00:00
|
|
|
boundbox_set_from_min_max(bb, min, max);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2010-06-28 11:07:02 +00:00
|
|
|
float *make_orco_mball(Object *ob, ListBase *dispbase)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
BoundBox *bb;
|
|
|
|
DispList *dl;
|
2008-02-26 16:20:36 +00:00
|
|
|
float *data, *orco, *orcodata;
|
2002-10-12 11:37:38 +00:00
|
|
|
float loc[3], size[3];
|
|
|
|
int a;
|
2008-02-26 16:20:36 +00:00
|
|
|
|
2003-04-26 13:07:59 +00:00
|
|
|
/* restore size and loc */
|
2002-10-12 11:37:38 +00:00
|
|
|
bb= ob->bb;
|
|
|
|
loc[0]= (bb->vec[0][0]+bb->vec[4][0])/2.0f;
|
|
|
|
size[0]= bb->vec[4][0]-loc[0];
|
|
|
|
loc[1]= (bb->vec[0][1]+bb->vec[2][1])/2.0f;
|
|
|
|
size[1]= bb->vec[2][1]-loc[1];
|
|
|
|
loc[2]= (bb->vec[0][2]+bb->vec[1][2])/2.0f;
|
|
|
|
size[2]= bb->vec[1][2]-loc[2];
|
|
|
|
|
2010-06-28 11:07:02 +00:00
|
|
|
dl= dispbase->first;
|
2008-02-26 18:30:41 +00:00
|
|
|
orcodata= MEM_mallocN(sizeof(float)*3*dl->nr, "MballOrco");
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
data= dl->verts;
|
2008-02-26 16:20:36 +00:00
|
|
|
orco= orcodata;
|
2002-10-12 11:37:38 +00:00
|
|
|
a= dl->nr;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (a--) {
|
2008-02-26 16:20:36 +00:00
|
|
|
orco[0]= (data[0]-loc[0])/size[0];
|
|
|
|
orco[1]= (data[1]-loc[1])/size[1];
|
|
|
|
orco[2]= (data[2]-loc[2])/size[2];
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
data+= 3;
|
2008-02-26 16:20:36 +00:00
|
|
|
orco+= 3;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2008-02-26 16:20:36 +00:00
|
|
|
|
|
|
|
return orcodata;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2010-11-18 04:26:50 +00:00
|
|
|
|
|
|
|
/* Note on mball basis stuff 2.5x (this is a can of worms)
|
2011-04-21 05:49:47 +00:00
|
|
|
* This really needs a rewrite/refactor its totally broken in anything other then basic cases
|
2010-11-18 04:26:50 +00:00
|
|
|
* Multiple Scenes + Set Scenes & mixing mball basis SHOULD work but fails to update the depsgraph on rename
|
|
|
|
* and linking into scenes or removal of basis mball. so take care when changing this code.
|
|
|
|
*
|
|
|
|
* Main idiot thing here is that the system returns find_basis_mball() objects which fail a is_basis_mball() test.
|
|
|
|
*
|
2011-04-21 05:49:47 +00:00
|
|
|
* Not only that but the depsgraph and their areas depend on this behavior!, so making small fixes here isn't worth it.
|
|
|
|
* - Campbell
|
2010-11-18 04:26:50 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
2003-12-08 13:30:04 +00:00
|
|
|
/** \brief Test, if Object *ob is basic MetaBall.
|
|
|
|
*
|
|
|
|
* It test last character of Object ID name. If last character
|
|
|
|
* is digit it return 0, else it return 1.
|
|
|
|
*/
|
2003-11-21 12:30:15 +00:00
|
|
|
int is_basis_mball(Object *ob)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
|
|
|
|
/* just a quick test */
|
|
|
|
len= strlen(ob->id.name);
|
2012-02-23 02:17:50 +00:00
|
|
|
if ( isdigit(ob->id.name[len-1]) ) return 0;
|
2003-11-21 12:30:15 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2010-06-27 12:45:09 +00:00
|
|
|
/* return nonzero if ob1 is a basis mball for ob */
|
2012-03-24 07:52:14 +00:00
|
|
|
int is_mball_basis_for (Object *ob1, Object *ob2)
|
2010-06-27 12:45:09 +00:00
|
|
|
{
|
|
|
|
int basis1nr, basis2nr;
|
2012-01-11 08:51:06 +00:00
|
|
|
char basis1name[MAX_ID_NAME], basis2name[MAX_ID_NAME];
|
2010-06-27 12:45:09 +00:00
|
|
|
|
2010-11-07 08:49:07 +00:00
|
|
|
BLI_split_name_num(basis1name, &basis1nr, ob1->id.name+2, '.');
|
|
|
|
BLI_split_name_num(basis2name, &basis2nr, ob2->id.name+2, '.');
|
2010-06-27 12:45:09 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (!strcmp(basis1name, basis2name)) return is_basis_mball(ob1);
|
2010-06-27 12:45:09 +00:00
|
|
|
else return 0;
|
|
|
|
}
|
|
|
|
|
2009-08-03 14:40:10 +00:00
|
|
|
/* \brief copy some properties from object to other metaball object with same base name
|
|
|
|
*
|
|
|
|
* When some properties (wiresize, threshold, update flags) of metaball are changed, then this properties
|
|
|
|
* are copied to all metaballs in same "group" (metaballs with same base name: MBall,
|
|
|
|
* MBall.001, MBall.002, etc). The most important is to copy properties to the base metaball,
|
|
|
|
* because this metaball influence polygonisation of metaballs. */
|
|
|
|
void copy_mball_properties(Scene *scene, Object *active_object)
|
|
|
|
{
|
2010-07-13 16:06:51 +00:00
|
|
|
Scene *sce_iter= scene;
|
2009-08-03 14:40:10 +00:00
|
|
|
Base *base;
|
|
|
|
Object *ob;
|
|
|
|
MetaBall *active_mball = (MetaBall*)active_object->data;
|
|
|
|
int basisnr, obnr;
|
2012-01-11 08:51:06 +00:00
|
|
|
char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
|
2009-08-03 14:40:10 +00:00
|
|
|
|
2010-11-07 08:49:07 +00:00
|
|
|
BLI_split_name_num(basisname, &basisnr, active_object->id.name+2, '.');
|
2009-08-03 14:40:10 +00:00
|
|
|
|
|
|
|
/* XXX recursion check, see scene.c, just too simple code this next_object() */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (F_ERROR==next_object(&sce_iter, 0, NULL, NULL))
|
2009-08-03 14:40:10 +00:00
|
|
|
return;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
while (next_object(&sce_iter, 1, &base, &ob)) {
|
2009-08-03 14:40:10 +00:00
|
|
|
if (ob->type==OB_MBALL) {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ob != active_object) {
|
2010-11-07 08:49:07 +00:00
|
|
|
BLI_split_name_num(obname, &obnr, ob->id.name+2, '.');
|
2009-08-03 14:40:10 +00:00
|
|
|
|
|
|
|
/* Object ob has to be in same "group" ... it means, that it has to have
|
|
|
|
* same base of its name */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (strcmp(obname, basisname)==0) {
|
2009-08-03 14:40:10 +00:00
|
|
|
MetaBall *mb= ob->data;
|
|
|
|
|
|
|
|
/* Copy properties from selected/edited metaball */
|
|
|
|
mb->wiresize= active_mball->wiresize;
|
|
|
|
mb->rendersize= active_mball->rendersize;
|
|
|
|
mb->thresh= active_mball->thresh;
|
|
|
|
mb->flag= active_mball->flag;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-12-08 13:30:04 +00:00
|
|
|
/** \brief This function finds basic MetaBall.
|
|
|
|
*
|
|
|
|
* Basic MetaBall doesn't include any number at the end of
|
|
|
|
* its name. All MetaBalls with same base of name can be
|
|
|
|
* blended. MetaBalls with different basic name can't be
|
|
|
|
* blended.
|
2010-11-18 04:26:50 +00:00
|
|
|
*
|
|
|
|
* warning!, is_basis_mball() can fail on returned object, see long note above.
|
2003-12-08 13:30:04 +00:00
|
|
|
*/
|
2009-01-04 14:14:06 +00:00
|
|
|
Object *find_basis_mball(Scene *scene, Object *basis)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2010-07-13 16:06:51 +00:00
|
|
|
Scene *sce_iter= scene;
|
2002-10-12 11:37:38 +00:00
|
|
|
Base *base;
|
2004-11-10 13:20:13 +00:00
|
|
|
Object *ob,*bob= basis;
|
|
|
|
MetaElem *ml=NULL;
|
|
|
|
int basisnr, obnr;
|
2012-01-11 08:51:06 +00:00
|
|
|
char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
|
2010-11-01 07:19:41 +00:00
|
|
|
|
2010-11-07 08:49:07 +00:00
|
|
|
BLI_split_name_num(basisname, &basisnr, basis->id.name+2, '.');
|
2004-11-10 13:20:13 +00:00
|
|
|
totelem= 0;
|
|
|
|
|
2009-06-08 20:08:19 +00:00
|
|
|
/* XXX recursion check, see scene.c, just too simple code this next_object() */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (F_ERROR==next_object(&sce_iter, 0, NULL, NULL))
|
2009-06-08 20:08:19 +00:00
|
|
|
return NULL;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
while (next_object(&sce_iter, 1, &base, &ob)) {
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2004-11-10 13:20:13 +00:00
|
|
|
if (ob->type==OB_MBALL) {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ob==bob) {
|
2009-01-02 19:10:35 +00:00
|
|
|
MetaBall *mb= ob->data;
|
|
|
|
|
2004-11-10 13:20:13 +00:00
|
|
|
/* if bob object is in edit mode, then dynamic list of all MetaElems
|
|
|
|
* is stored in editelems */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mb->editelems) ml= mb->editelems->first;
|
2004-11-10 13:20:13 +00:00
|
|
|
/* if bob object is in object mode */
|
2009-01-02 19:10:35 +00:00
|
|
|
else ml= mb->elems.first;
|
2004-11-10 13:20:13 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2010-11-07 08:49:07 +00:00
|
|
|
BLI_split_name_num(obname, &obnr, ob->id.name+2, '.');
|
2004-11-10 13:20:13 +00:00
|
|
|
|
|
|
|
/* object ob has to be in same "group" ... it means, that it has to have
|
|
|
|
* same base of its name */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (strcmp(obname, basisname)==0) {
|
2009-01-02 19:10:35 +00:00
|
|
|
MetaBall *mb= ob->data;
|
|
|
|
|
2004-11-10 13:20:13 +00:00
|
|
|
/* if object is in edit mode, then dynamic list of all MetaElems
|
|
|
|
* is stored in editelems */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mb->editelems) ml= mb->editelems->first;
|
2009-01-02 19:10:35 +00:00
|
|
|
/* if bob object is in object mode */
|
|
|
|
else ml= mb->elems.first;
|
2004-11-10 13:20:13 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (obnr < basisnr) {
|
|
|
|
if (!(ob->flag & OB_FROMDUPLI)) {
|
2004-11-20 11:59:44 +00:00
|
|
|
basis= ob;
|
|
|
|
basisnr= obnr;
|
|
|
|
}
|
2004-11-10 13:20:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
while (ml) {
|
|
|
|
if (!(ml->flag & MB_HIDE)) totelem++;
|
2004-11-10 13:20:13 +00:00
|
|
|
ml= ml->next;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return basis;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ******************** ARITH ************************* */
|
|
|
|
|
2003-04-26 13:07:59 +00:00
|
|
|
/* BASED AT CODE (but mostly rewritten) :
|
2002-10-12 11:37:38 +00:00
|
|
|
* C code from the article
|
|
|
|
* "An Implicit Surface Polygonizer"
|
|
|
|
* by Jules Bloomenthal, jbloom@beauty.gmu.edu
|
|
|
|
* in "Graphics Gems IV", Academic Press, 1994
|
2012-03-03 20:19:11 +00:00
|
|
|
*
|
2002-10-12 11:37:38 +00:00
|
|
|
* Authored by Jules Bloomenthal, Xerox PARC.
|
|
|
|
* Copyright (c) Xerox Corporation, 1991. All rights reserved.
|
|
|
|
* Permission is granted to reproduce, use and distribute this code for
|
|
|
|
* any and all purposes, provided that this notice appears in all copies. */
|
|
|
|
|
|
|
|
#define RES 12 /* # converge iterations */
|
|
|
|
|
|
|
|
#define L 0 /* left direction: -x, -i */
|
|
|
|
#define R 1 /* right direction: +x, +i */
|
|
|
|
#define B 2 /* bottom direction: -y, -j */
|
|
|
|
#define T 3 /* top direction: +y, +j */
|
|
|
|
#define N 4 /* near direction: -z, -k */
|
|
|
|
#define F 5 /* far direction: +z, +k */
|
|
|
|
#define LBN 0 /* left bottom near corner */
|
|
|
|
#define LBF 1 /* left bottom far corner */
|
|
|
|
#define LTN 2 /* left top near corner */
|
|
|
|
#define LTF 3 /* left top far corner */
|
|
|
|
#define RBN 4 /* right bottom near corner */
|
|
|
|
#define RBF 5 /* right bottom far corner */
|
|
|
|
#define RTN 6 /* right top near corner */
|
|
|
|
#define RTF 7 /* right top far corner */
|
|
|
|
|
|
|
|
/* the LBN corner of cube (i, j, k), corresponds with location
|
2008-05-12 16:22:49 +00:00
|
|
|
* (i-0.5)*size, (j-0.5)*size, (k-0.5)*size) */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
#define HASHBIT (5)
|
2003-12-08 13:30:04 +00:00
|
|
|
#define HASHSIZE (size_t)(1<<(3*HASHBIT)) /*! < hash table size (32768) */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
#define HASH(i,j,k) ((((( (i) & 31)<<5) | ( (j) & 31))<<5 ) | ( (k) & 31) )
|
|
|
|
|
|
|
|
#define MB_BIT(i, bit) (((i)>>(bit))&1)
|
|
|
|
#define FLIP(i,bit) ((i)^1<<(bit)) /* flip the given bit of i */
|
|
|
|
|
|
|
|
|
2004-06-29 17:10:13 +00:00
|
|
|
/* **************** POLYGONIZATION ************************ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-02-28 14:05:00 +00:00
|
|
|
void calc_mballco(MetaElem *ml, float vec[3])
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->mat) {
|
2012-04-24 22:50:49 +00:00
|
|
|
mul_m4_v3((float (*)[4])ml->mat, vec);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float densfunc(MetaElem *ball, float x, float y, float z)
|
|
|
|
{
|
|
|
|
float dist2 = 0.0, dx, dy, dz;
|
|
|
|
float vec[3];
|
2003-09-05 13:54:22 +00:00
|
|
|
|
2004-06-29 17:10:13 +00:00
|
|
|
vec[0]= x;
|
|
|
|
vec[1]= y;
|
|
|
|
vec[2]= z;
|
2012-04-24 22:50:49 +00:00
|
|
|
mul_m4_v3((float (*)[4])ball->imat, vec);
|
2004-06-29 17:10:13 +00:00
|
|
|
dx= vec[0];
|
|
|
|
dy= vec[1];
|
|
|
|
dz= vec[2];
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ball->type==MB_BALL) {
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
else if (ball->type==MB_TUBEX) {
|
|
|
|
if ( dx > ball->len) dx-= ball->len;
|
|
|
|
else if (dx< -ball->len) dx+= ball->len;
|
2003-09-05 13:54:22 +00:00
|
|
|
else dx= 0.0;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
else if (ball->type==MB_TUBEY) {
|
|
|
|
if ( dy > ball->len) dy-= ball->len;
|
|
|
|
else if (dy< -ball->len) dy+= ball->len;
|
2003-09-05 13:54:22 +00:00
|
|
|
else dy= 0.0;
|
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
else if (ball->type==MB_TUBEZ) {
|
|
|
|
if ( dz > ball->len) dz-= ball->len;
|
|
|
|
else if (dz< -ball->len) dz+= ball->len;
|
2003-09-05 13:54:22 +00:00
|
|
|
else dz= 0.0;
|
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
else if (ball->type==MB_TUBE) {
|
|
|
|
if ( dx > ball->expx) dx-= ball->expx;
|
|
|
|
else if (dx< -ball->expx) dx+= ball->expx;
|
2003-09-05 13:54:22 +00:00
|
|
|
else dx= 0.0;
|
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
else if (ball->type==MB_PLANE) {
|
|
|
|
if ( dx > ball->expx) dx-= ball->expx;
|
|
|
|
else if (dx< -ball->expx) dx+= ball->expx;
|
2003-09-05 13:54:22 +00:00
|
|
|
else dx= 0.0;
|
2012-02-23 02:17:50 +00:00
|
|
|
if ( dy > ball->expy) dy-= ball->expy;
|
|
|
|
else if (dy< -ball->expy) dy+= ball->expy;
|
2003-09-05 13:54:22 +00:00
|
|
|
else dy= 0.0;
|
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
else if (ball->type==MB_ELIPSOID) {
|
2003-09-05 13:54:22 +00:00
|
|
|
dx *= 1/ball->expx;
|
|
|
|
dy *= 1/ball->expy;
|
|
|
|
dz *= 1/ball->expz;
|
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
else if (ball->type==MB_CUBE) {
|
|
|
|
if ( dx > ball->expx) dx-= ball->expx;
|
|
|
|
else if (dx< -ball->expx) dx+= ball->expx;
|
2003-09-05 13:54:22 +00:00
|
|
|
else dx= 0.0;
|
2012-02-23 02:17:50 +00:00
|
|
|
if ( dy > ball->expy) dy-= ball->expy;
|
|
|
|
else if (dy< -ball->expy) dy+= ball->expy;
|
2003-09-05 13:54:22 +00:00
|
|
|
else dy= 0.0;
|
2012-02-23 02:17:50 +00:00
|
|
|
if ( dz > ball->expz) dz-= ball->expz;
|
|
|
|
else if (dz< -ball->expz) dz+= ball->expz;
|
2003-09-05 13:54:22 +00:00
|
|
|
else dz= 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
dist2= (dx*dx + dy*dy + dz*dz);
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ball->flag & MB_NEGATIVE) {
|
2002-10-12 11:37:38 +00:00
|
|
|
dist2= 1.0f-(dist2/ball->rad2);
|
2012-02-23 02:17:50 +00:00
|
|
|
if (dist2 < 0.0f) return 0.5f;
|
2003-09-05 13:54:22 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
return 0.5f-ball->s*dist2*dist2*dist2;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dist2= 1.0f-(dist2/ball->rad2);
|
2012-02-23 02:17:50 +00:00
|
|
|
if (dist2 < 0.0f) return -0.5f;
|
2003-09-05 13:54:22 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
return ball->s*dist2*dist2*dist2 -0.5f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-06-29 17:10:13 +00:00
|
|
|
octal_node* find_metaball_octal_node(octal_node *node, float x, float y, float z, short depth)
|
|
|
|
{
|
2012-02-23 02:17:50 +00:00
|
|
|
if (!depth) return node;
|
2004-06-29 17:10:13 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (z < node->z) {
|
|
|
|
if (y < node->y) {
|
|
|
|
if (x < node->x) {
|
|
|
|
if (node->nodes[0])
|
2004-06-29 17:10:13 +00:00
|
|
|
return find_metaball_octal_node(node->nodes[0],x,y,z,depth--);
|
|
|
|
else
|
|
|
|
return node;
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (node->nodes[1])
|
2004-06-29 17:10:13 +00:00
|
|
|
return find_metaball_octal_node(node->nodes[1],x,y,z,depth--);
|
|
|
|
else
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (x < node->x) {
|
|
|
|
if (node->nodes[3])
|
2004-06-29 17:10:13 +00:00
|
|
|
return find_metaball_octal_node(node->nodes[3],x,y,z,depth--);
|
|
|
|
else
|
|
|
|
return node;
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (node->nodes[2])
|
2004-06-29 17:10:13 +00:00
|
|
|
return find_metaball_octal_node(node->nodes[2],x,y,z,depth--);
|
|
|
|
else
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (y < node->y) {
|
|
|
|
if (x < node->x) {
|
|
|
|
if (node->nodes[4])
|
2004-06-29 17:10:13 +00:00
|
|
|
return find_metaball_octal_node(node->nodes[4],x,y,z,depth--);
|
|
|
|
else
|
|
|
|
return node;
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (node->nodes[5])
|
2004-06-29 17:10:13 +00:00
|
|
|
return find_metaball_octal_node(node->nodes[5],x,y,z,depth--);
|
|
|
|
else
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (x < node->x) {
|
|
|
|
if (node->nodes[7])
|
2004-06-29 17:10:13 +00:00
|
|
|
return find_metaball_octal_node(node->nodes[7],x,y,z,depth--);
|
|
|
|
else
|
|
|
|
return node;
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (node->nodes[6])
|
2004-06-29 17:10:13 +00:00
|
|
|
return find_metaball_octal_node(node->nodes[6],x,y,z,depth--);
|
|
|
|
else
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
float metaball(float x, float y, float z)
|
|
|
|
/* float x, y, z; */
|
|
|
|
{
|
2004-06-29 17:10:13 +00:00
|
|
|
struct octal_node *node;
|
|
|
|
struct ml_pointer *ml_p;
|
2002-10-12 11:37:38 +00:00
|
|
|
float dens=0;
|
|
|
|
int a;
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (totelem > 1) {
|
2004-06-29 17:10:13 +00:00
|
|
|
node= find_metaball_octal_node(metaball_tree->first, x, y, z, metaball_tree->depth);
|
2012-02-23 02:17:50 +00:00
|
|
|
if (node) {
|
2004-06-29 17:10:13 +00:00
|
|
|
ml_p= node->elems.first;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
while (ml_p) {
|
2004-06-29 17:10:13 +00:00
|
|
|
dens+=densfunc(ml_p->ml, x, y, z);
|
|
|
|
ml_p= ml_p->next;
|
|
|
|
}
|
|
|
|
|
2011-03-28 04:22:50 +00:00
|
|
|
dens+= -0.5f*(metaball_tree->pos - node->pos);
|
|
|
|
dens+= 0.5f*(metaball_tree->neg - node->neg);
|
2004-06-29 17:10:13 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
|
|
|
for (a=0; a<totelem; a++) {
|
2012-03-11 19:09:01 +00:00
|
|
|
dens += densfunc(mainb[a], x, y, z);
|
2004-06-29 17:10:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2012-03-11 19:09:01 +00:00
|
|
|
dens += densfunc(mainb[0], x, y, z);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return thresh - dens;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ******************************************** */
|
|
|
|
|
2011-02-13 10:52:18 +00:00
|
|
|
static int *indices=NULL;
|
|
|
|
static int totindex, curindex;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
void accum_mballfaces(int i1, int i2, int i3, int i4)
|
|
|
|
{
|
|
|
|
int *newi, *cur;
|
|
|
|
/* static int i=0; I would like to delete altogether, but I don't dare to, yet */
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (totindex==curindex) {
|
2002-10-12 11:37:38 +00:00
|
|
|
totindex+= 256;
|
|
|
|
newi= MEM_mallocN(4*sizeof(int)*totindex, "vertindex");
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (indices) {
|
2002-10-12 11:37:38 +00:00
|
|
|
memcpy(newi, indices, 4*sizeof(int)*(totindex-256));
|
|
|
|
MEM_freeN(indices);
|
|
|
|
}
|
|
|
|
indices= newi;
|
|
|
|
}
|
|
|
|
|
|
|
|
cur= indices+4*curindex;
|
|
|
|
|
2011-04-21 05:49:47 +00:00
|
|
|
/* displists now support array drawing, we treat tri's as fake quad */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
cur[0]= i1;
|
|
|
|
cur[1]= i2;
|
|
|
|
cur[2]= i3;
|
2012-02-23 02:17:50 +00:00
|
|
|
if (i4==0)
|
2006-11-20 21:25:02 +00:00
|
|
|
cur[3]= i3;
|
|
|
|
else
|
|
|
|
cur[3]= i4;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
curindex++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ******************* MEMORY MANAGEMENT *********************** */
|
|
|
|
void *new_pgn_element(int size)
|
|
|
|
{
|
2003-04-26 13:07:59 +00:00
|
|
|
/* during polygonize 1000s of elements are allocated
|
2011-01-02 11:06:50 +00:00
|
|
|
* and never freed in between. Freeing only done at the end.
|
2002-10-12 11:37:38 +00:00
|
|
|
*/
|
|
|
|
int blocksize= 16384;
|
2003-04-26 13:07:59 +00:00
|
|
|
static int offs= 0; /* the current free address */
|
2011-02-13 10:52:18 +00:00
|
|
|
static struct pgn_elements *cur= NULL;
|
|
|
|
static ListBase lb= {NULL, NULL};
|
2002-10-12 11:37:38 +00:00
|
|
|
void *adr;
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (size>10000 || size==0) {
|
2002-10-12 11:37:38 +00:00
|
|
|
printf("incorrect use of new_pgn_element\n");
|
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
else if (size== -1) {
|
2002-10-12 11:37:38 +00:00
|
|
|
cur= lb.first;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (cur) {
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(cur->data);
|
|
|
|
cur= cur->next;
|
|
|
|
}
|
|
|
|
BLI_freelistN(&lb);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
size= 4*( (size+3)/4 );
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (cur) {
|
|
|
|
if (size+offs < blocksize) {
|
2002-10-12 11:37:38 +00:00
|
|
|
adr= (void *) (cur->data+offs);
|
2011-11-11 13:09:14 +00:00
|
|
|
offs+= size;
|
2002-10-12 11:37:38 +00:00
|
|
|
return adr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cur= MEM_callocN( sizeof(struct pgn_elements), "newpgn");
|
|
|
|
cur->data= MEM_callocN(blocksize, "newpgn");
|
|
|
|
BLI_addtail(&lb, cur);
|
|
|
|
|
|
|
|
offs= size;
|
|
|
|
return cur->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
void freepolygonize(PROCESS *p)
|
|
|
|
{
|
|
|
|
MEM_freeN(p->corners);
|
|
|
|
MEM_freeN(p->edges);
|
|
|
|
MEM_freeN(p->centers);
|
|
|
|
|
|
|
|
new_pgn_element(-1);
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (p->vertices.ptr) MEM_freeN(p->vertices.ptr);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**** Cubical Polygonization (optional) ****/
|
|
|
|
|
|
|
|
#define LB 0 /* left bottom edge */
|
|
|
|
#define LT 1 /* left top edge */
|
|
|
|
#define LN 2 /* left near edge */
|
|
|
|
#define LF 3 /* left far edge */
|
|
|
|
#define RB 4 /* right bottom edge */
|
|
|
|
#define RT 5 /* right top edge */
|
|
|
|
#define RN 6 /* right near edge */
|
|
|
|
#define RF 7 /* right far edge */
|
|
|
|
#define BN 8 /* bottom near edge */
|
|
|
|
#define BF 9 /* bottom far edge */
|
|
|
|
#define TN 10 /* top near edge */
|
|
|
|
#define TF 11 /* top far edge */
|
|
|
|
|
|
|
|
static INTLISTS *cubetable[256];
|
|
|
|
|
2004-06-29 17:10:13 +00:00
|
|
|
/* edge: LB, LT, LN, LF, RB, RT, RN, RF, BN, BF, TN, TF */
|
2002-10-12 11:37:38 +00:00
|
|
|
static int corner1[12] = {
|
|
|
|
LBN,LTN,LBN,LBF,RBN,RTN,RBN,RBF,LBN,LBF,LTN,LTF};
|
|
|
|
static int corner2[12] = {
|
|
|
|
LBF,LTF,LTN,LTF,RBF,RTF,RTN,RTF,RBN,RBF,RTN,RTF};
|
|
|
|
static int leftface[12] = {
|
|
|
|
B, L, L, F, R, T, N, R, N, B, T, F};
|
|
|
|
/* face on left when going corner1 to corner2 */
|
|
|
|
static int rightface[12] = {
|
|
|
|
L, T, N, L, B, R, R, F, B, F, N, T};
|
|
|
|
/* face on right when going corner1 to corner2 */
|
|
|
|
|
|
|
|
|
|
|
|
/* docube: triangulate the cube directly, without decomposition */
|
|
|
|
|
2003-09-05 13:54:22 +00:00
|
|
|
void docube(CUBE *cube, PROCESS *p, MetaBall *mb)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
INTLISTS *polys;
|
|
|
|
CORNER *c1, *c2;
|
|
|
|
int i, index = 0, count, indexar[8];
|
|
|
|
|
2011-03-28 04:22:50 +00:00
|
|
|
for (i = 0; i < 8; i++) if (cube->corners[i]->value > 0.0f) index += (1<<i);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
for (polys = cubetable[index]; polys; polys = polys->next) {
|
|
|
|
INTLIST *edges;
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
|
|
|
|
for (edges = polys->list; edges; edges = edges->next) {
|
|
|
|
c1 = cube->corners[corner1[edges->i]];
|
|
|
|
c2 = cube->corners[corner2[edges->i]];
|
|
|
|
|
2003-09-05 13:54:22 +00:00
|
|
|
indexar[count] = vertid(c1, c2, p, mb);
|
2002-10-12 11:37:38 +00:00
|
|
|
count++;
|
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
if (count>2) {
|
2002-10-12 11:37:38 +00:00
|
|
|
switch(count) {
|
|
|
|
case 3:
|
|
|
|
accum_mballfaces(indexar[2], indexar[1], indexar[0], 0);
|
|
|
|
break;
|
|
|
|
case 4:
|
2012-02-23 02:17:50 +00:00
|
|
|
if (indexar[0]==0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]);
|
2002-10-12 11:37:38 +00:00
|
|
|
else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]);
|
|
|
|
break;
|
|
|
|
case 5:
|
2012-02-23 02:17:50 +00:00
|
|
|
if (indexar[0]==0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]);
|
2002-10-12 11:37:38 +00:00
|
|
|
else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]);
|
|
|
|
|
|
|
|
accum_mballfaces(indexar[4], indexar[3], indexar[0], 0);
|
|
|
|
break;
|
|
|
|
case 6:
|
2012-02-23 02:17:50 +00:00
|
|
|
if (indexar[0]==0) {
|
2002-10-12 11:37:38 +00:00
|
|
|
accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]);
|
|
|
|
accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]);
|
|
|
|
accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 7:
|
2012-02-23 02:17:50 +00:00
|
|
|
if (indexar[0]==0) {
|
2002-10-12 11:37:38 +00:00
|
|
|
accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]);
|
|
|
|
accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]);
|
|
|
|
accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
accum_mballfaces(indexar[6], indexar[5], indexar[0], 0);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* testface: given cube at lattice (i, j, k), and four corners of face,
|
|
|
|
* if surface crosses face, compute other four corners of adjacent cube
|
|
|
|
* and add new cube to cube stack */
|
|
|
|
|
|
|
|
void testface(int i, int j, int k, CUBE* old, int bit, int c1, int c2, int c3, int c4, PROCESS *p)
|
|
|
|
{
|
|
|
|
CUBE newc;
|
|
|
|
CUBES *oldcubes = p->cubes;
|
|
|
|
CORNER *corn1, *corn2, *corn3, *corn4;
|
|
|
|
int n, pos;
|
|
|
|
|
|
|
|
corn1= old->corners[c1];
|
|
|
|
corn2= old->corners[c2];
|
|
|
|
corn3= old->corners[c3];
|
|
|
|
corn4= old->corners[c4];
|
|
|
|
|
2011-03-28 04:22:50 +00:00
|
|
|
pos = corn1->value > 0.0f ? 1 : 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/* test if no surface crossing */
|
2012-02-23 02:17:50 +00:00
|
|
|
if ( (corn2->value > 0) == pos && (corn3->value > 0) == pos && (corn4->value > 0) == pos) return;
|
2002-10-12 11:37:38 +00:00
|
|
|
/* test if cube out of bounds */
|
2003-08-09 17:09:11 +00:00
|
|
|
/*if ( abs(i) > p->bounds || abs(j) > p->bounds || abs(k) > p->bounds) return;*/
|
2002-10-12 11:37:38 +00:00
|
|
|
/* test if already visited (always as last) */
|
|
|
|
if (setcenter(p->centers, i, j, k)) return;
|
|
|
|
|
|
|
|
|
|
|
|
/* create new cube and add cube to top of stack: */
|
|
|
|
p->cubes = (CUBES *) new_pgn_element(sizeof(CUBES));
|
|
|
|
p->cubes->next = oldcubes;
|
|
|
|
|
|
|
|
newc.i = i;
|
|
|
|
newc.j = j;
|
|
|
|
newc.k = k;
|
|
|
|
for (n = 0; n < 8; n++) newc.corners[n] = NULL;
|
|
|
|
|
|
|
|
newc.corners[FLIP(c1, bit)] = corn1;
|
|
|
|
newc.corners[FLIP(c2, bit)] = corn2;
|
|
|
|
newc.corners[FLIP(c3, bit)] = corn3;
|
|
|
|
newc.corners[FLIP(c4, bit)] = corn4;
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (newc.corners[0]==NULL) newc.corners[0] = setcorner(p, i, j, k);
|
|
|
|
if (newc.corners[1]==NULL) newc.corners[1] = setcorner(p, i, j, k+1);
|
|
|
|
if (newc.corners[2]==NULL) newc.corners[2] = setcorner(p, i, j+1, k);
|
|
|
|
if (newc.corners[3]==NULL) newc.corners[3] = setcorner(p, i, j+1, k+1);
|
|
|
|
if (newc.corners[4]==NULL) newc.corners[4] = setcorner(p, i+1, j, k);
|
|
|
|
if (newc.corners[5]==NULL) newc.corners[5] = setcorner(p, i+1, j, k+1);
|
|
|
|
if (newc.corners[6]==NULL) newc.corners[6] = setcorner(p, i+1, j+1, k);
|
|
|
|
if (newc.corners[7]==NULL) newc.corners[7] = setcorner(p, i+1, j+1, k+1);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
p->cubes->cube= newc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* setcorner: return corner with the given lattice location
|
2012-03-03 20:19:11 +00:00
|
|
|
* set (and cache) its function value */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
CORNER *setcorner (PROCESS* p, int i, int j, int k)
|
|
|
|
{
|
|
|
|
/* for speed, do corner value caching here */
|
|
|
|
CORNER *c;
|
|
|
|
int index;
|
|
|
|
|
2003-04-26 13:07:59 +00:00
|
|
|
/* does corner exist? */
|
2002-10-12 11:37:38 +00:00
|
|
|
index = HASH(i, j, k);
|
|
|
|
c = p->corners[index];
|
|
|
|
|
|
|
|
for (; c != NULL; c = c->next) {
|
|
|
|
if (c->i == i && c->j == j && c->k == k) {
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
c = (CORNER *) new_pgn_element(sizeof(CORNER));
|
|
|
|
|
|
|
|
c->i = i;
|
2010-07-06 11:44:45 +00:00
|
|
|
c->x = ((float)i-0.5f)*p->size;
|
2002-10-12 11:37:38 +00:00
|
|
|
c->j = j;
|
2010-07-06 11:44:45 +00:00
|
|
|
c->y = ((float)j-0.5f)*p->size;
|
2002-10-12 11:37:38 +00:00
|
|
|
c->k = k;
|
2010-07-06 11:44:45 +00:00
|
|
|
c->z = ((float)k-0.5f)*p->size;
|
2002-10-12 11:37:38 +00:00
|
|
|
c->value = p->function(c->x, c->y, c->z);
|
|
|
|
|
|
|
|
c->next = p->corners[index];
|
|
|
|
p->corners[index] = c;
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* nextcwedge: return next clockwise edge from given edge around given face */
|
|
|
|
|
|
|
|
int nextcwedge (int edge, int face)
|
|
|
|
{
|
|
|
|
switch (edge) {
|
|
|
|
case LB:
|
|
|
|
return (face == L)? LF : BN;
|
|
|
|
case LT:
|
|
|
|
return (face == L)? LN : TF;
|
|
|
|
case LN:
|
|
|
|
return (face == L)? LB : TN;
|
|
|
|
case LF:
|
|
|
|
return (face == L)? LT : BF;
|
|
|
|
case RB:
|
|
|
|
return (face == R)? RN : BF;
|
|
|
|
case RT:
|
|
|
|
return (face == R)? RF : TN;
|
|
|
|
case RN:
|
|
|
|
return (face == R)? RT : BN;
|
|
|
|
case RF:
|
|
|
|
return (face == R)? RB : TF;
|
|
|
|
case BN:
|
|
|
|
return (face == B)? RB : LN;
|
|
|
|
case BF:
|
|
|
|
return (face == B)? LB : RF;
|
|
|
|
case TN:
|
|
|
|
return (face == T)? LT : RN;
|
|
|
|
case TF:
|
|
|
|
return (face == T)? RT : LF;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* otherface: return face adjoining edge that is not the given face */
|
|
|
|
|
|
|
|
int otherface (int edge, int face)
|
|
|
|
{
|
|
|
|
int other = leftface[edge];
|
|
|
|
return face == other? rightface[edge] : other;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* makecubetable: create the 256 entry table for cubical polygonization */
|
|
|
|
|
|
|
|
void makecubetable (void)
|
|
|
|
{
|
|
|
|
static int isdone= 0;
|
|
|
|
int i, e, c, done[12], pos[8];
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (isdone) return;
|
2002-10-12 11:37:38 +00:00
|
|
|
isdone= 1;
|
|
|
|
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
|
|
for (e = 0; e < 12; e++) done[e] = 0;
|
|
|
|
for (c = 0; c < 8; c++) pos[c] = MB_BIT(i, c);
|
|
|
|
for (e = 0; e < 12; e++)
|
|
|
|
if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) {
|
2011-02-13 10:52:18 +00:00
|
|
|
INTLIST *ints = NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
INTLISTS *lists = (INTLISTS *) MEM_callocN(sizeof(INTLISTS), "mball_intlist");
|
|
|
|
int start = e, edge = e;
|
|
|
|
|
|
|
|
/* get face that is to right of edge from pos to neg corner: */
|
|
|
|
int face = pos[corner1[e]]? rightface[e] : leftface[e];
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
edge = nextcwedge(edge, face);
|
|
|
|
done[edge] = 1;
|
|
|
|
if (pos[corner1[edge]] != pos[corner2[edge]]) {
|
|
|
|
INTLIST *tmp = ints;
|
|
|
|
|
|
|
|
ints = (INTLIST *) MEM_callocN(sizeof(INTLIST), "mball_intlist");
|
|
|
|
ints->i = edge;
|
|
|
|
ints->next = tmp; /* add edge to head of list */
|
|
|
|
|
|
|
|
if (edge == start) break;
|
|
|
|
face = otherface(edge, face);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lists->list = ints; /* add ints to head of table entry */
|
|
|
|
lists->next = cubetable[i];
|
|
|
|
cubetable[i] = lists;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_freecubetable(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
INTLISTS *lists, *nlists;
|
|
|
|
INTLIST *ints, *nints;
|
|
|
|
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
|
|
lists= cubetable[i];
|
2012-03-24 06:18:31 +00:00
|
|
|
while (lists) {
|
2002-10-12 11:37:38 +00:00
|
|
|
nlists= lists->next;
|
|
|
|
|
|
|
|
ints= lists->list;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (ints) {
|
2002-10-12 11:37:38 +00:00
|
|
|
nints= ints->next;
|
|
|
|
MEM_freeN(ints);
|
|
|
|
ints= nints;
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(lists);
|
|
|
|
lists= nlists;
|
|
|
|
}
|
2011-02-13 10:52:18 +00:00
|
|
|
cubetable[i]= NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**** Storage ****/
|
|
|
|
|
|
|
|
/* setcenter: set (i,j,k) entry of table[]
|
|
|
|
* return 1 if already set; otherwise, set and return 0 */
|
|
|
|
|
|
|
|
int setcenter(CENTERLIST *table[], int i, int j, int k)
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
CENTERLIST *newc, *l, *q;
|
|
|
|
|
|
|
|
index= HASH(i, j, k);
|
|
|
|
q= table[index];
|
|
|
|
|
|
|
|
for (l = q; l != NULL; l = l->next) {
|
|
|
|
if (l->i == i && l->j == j && l->k == k) return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
newc = (CENTERLIST *) new_pgn_element(sizeof(CENTERLIST));
|
|
|
|
newc->i = i;
|
|
|
|
newc->j = j;
|
|
|
|
newc->k = k;
|
|
|
|
newc->next = q;
|
|
|
|
table[index] = newc;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* setedge: set vertex id for edge */
|
|
|
|
|
|
|
|
void setedge (EDGELIST *table[],
|
|
|
|
int i1, int j1,
|
|
|
|
int k1, int i2,
|
|
|
|
int j2, int k2,
|
|
|
|
int vid)
|
|
|
|
{
|
|
|
|
unsigned int index;
|
|
|
|
EDGELIST *newe;
|
|
|
|
|
|
|
|
if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) {
|
|
|
|
int t=i1;
|
|
|
|
i1=i2;
|
|
|
|
i2=t;
|
|
|
|
t=j1;
|
|
|
|
j1=j2;
|
|
|
|
j2=t;
|
|
|
|
t=k1;
|
|
|
|
k1=k2;
|
|
|
|
k2=t;
|
|
|
|
}
|
|
|
|
index = HASH(i1, j1, k1) + HASH(i2, j2, k2);
|
|
|
|
newe = (EDGELIST *) new_pgn_element(sizeof(EDGELIST));
|
|
|
|
newe->i1 = i1;
|
|
|
|
newe->j1 = j1;
|
|
|
|
newe->k1 = k1;
|
|
|
|
newe->i2 = i2;
|
|
|
|
newe->j2 = j2;
|
|
|
|
newe->k2 = k2;
|
|
|
|
newe->vid = vid;
|
|
|
|
newe->next = table[index];
|
|
|
|
table[index] = newe;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* getedge: return vertex id for edge; return -1 if not set */
|
|
|
|
|
|
|
|
int getedge (EDGELIST *table[],
|
|
|
|
int i1, int j1, int k1,
|
|
|
|
int i2, int j2, int k2)
|
|
|
|
{
|
|
|
|
EDGELIST *q;
|
|
|
|
|
|
|
|
if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) {
|
|
|
|
int t=i1;
|
|
|
|
i1=i2;
|
|
|
|
i2=t;
|
|
|
|
t=j1;
|
|
|
|
j1=j2;
|
|
|
|
j2=t;
|
|
|
|
t=k1;
|
|
|
|
k1=k2;
|
|
|
|
k2=t;
|
|
|
|
}
|
|
|
|
q = table[HASH(i1, j1, k1)+HASH(i2, j2, k2)];
|
|
|
|
for (; q != NULL; q = q->next)
|
|
|
|
if (q->i1 == i1 && q->j1 == j1 && q->k1 == k1 &&
|
2010-03-22 09:30:00 +00:00
|
|
|
q->i2 == i2 && q->j2 == j2 && q->k2 == k2)
|
2002-10-12 11:37:38 +00:00
|
|
|
return q->vid;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**** Vertices ****/
|
|
|
|
|
|
|
|
#undef R
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* vertid: return index for vertex on edge:
|
|
|
|
* c1->value and c2->value are presumed of different sign
|
|
|
|
* return saved index if any; else compute vertex and save */
|
|
|
|
|
|
|
|
/* addtovertices: add v to sequence of vertices */
|
|
|
|
|
|
|
|
void addtovertices (VERTICES *vertices, VERTEX v)
|
|
|
|
{
|
|
|
|
if (vertices->count == vertices->max) {
|
|
|
|
int i;
|
|
|
|
VERTEX *newv;
|
|
|
|
vertices->max = vertices->count == 0 ? 10 : 2*vertices->count;
|
|
|
|
newv = (VERTEX *) MEM_callocN(vertices->max * sizeof(VERTEX), "addtovertices");
|
|
|
|
|
|
|
|
for (i = 0; i < vertices->count; i++) newv[i] = vertices->ptr[i];
|
|
|
|
|
|
|
|
if (vertices->ptr != NULL) MEM_freeN(vertices->ptr);
|
|
|
|
vertices->ptr = newv;
|
|
|
|
}
|
|
|
|
vertices->ptr[vertices->count++] = v;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vnormal: compute unit length surface normal at point */
|
|
|
|
|
|
|
|
void vnormal (MB_POINT *point, PROCESS *p, MB_POINT *v)
|
|
|
|
{
|
|
|
|
float delta= 0.2f*p->delta;
|
|
|
|
float f = p->function(point->x, point->y, point->z);
|
|
|
|
|
|
|
|
v->x = p->function(point->x+delta, point->y, point->z)-f;
|
|
|
|
v->y = p->function(point->x, point->y+delta, point->z)-f;
|
|
|
|
v->z = p->function(point->x, point->y, point->z+delta)-f;
|
2011-03-28 04:22:50 +00:00
|
|
|
f = sqrtf(v->x*v->x + v->y*v->y + v->z*v->z);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2011-03-28 04:22:50 +00:00
|
|
|
if (f != 0.0f) {
|
2002-10-12 11:37:38 +00:00
|
|
|
v->x /= f;
|
|
|
|
v->y /= f;
|
|
|
|
v->z /= f;
|
|
|
|
}
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (FALSE) {
|
2002-10-12 11:37:38 +00:00
|
|
|
MB_POINT temp;
|
|
|
|
|
2011-03-28 04:22:50 +00:00
|
|
|
delta *= 2.0f;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
f = p->function(point->x, point->y, point->z);
|
|
|
|
|
|
|
|
temp.x = p->function(point->x+delta, point->y, point->z)-f;
|
|
|
|
temp.y = p->function(point->x, point->y+delta, point->z)-f;
|
|
|
|
temp.z = p->function(point->x, point->y, point->z+delta)-f;
|
2011-03-28 04:22:50 +00:00
|
|
|
f = sqrtf(temp.x*temp.x + temp.y*temp.y + temp.z*temp.z);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2011-03-28 04:22:50 +00:00
|
|
|
if (f != 0.0f) {
|
2002-10-12 11:37:38 +00:00
|
|
|
temp.x /= f;
|
|
|
|
temp.y /= f;
|
|
|
|
temp.z /= f;
|
|
|
|
|
|
|
|
v->x+= temp.x;
|
|
|
|
v->y+= temp.y;
|
|
|
|
v->z+= temp.z;
|
|
|
|
|
2011-03-28 04:22:50 +00:00
|
|
|
f = sqrtf(v->x*v->x + v->y*v->y + v->z*v->z);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2011-03-28 04:22:50 +00:00
|
|
|
if (f != 0.0f) {
|
2002-10-12 11:37:38 +00:00
|
|
|
v->x /= f;
|
|
|
|
v->y /= f;
|
|
|
|
v->z /= f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-09-05 13:54:22 +00:00
|
|
|
int vertid (CORNER *c1, CORNER *c2, PROCESS *p, MetaBall *mb)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
VERTEX v;
|
|
|
|
MB_POINT a, b;
|
|
|
|
int vid = getedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k);
|
|
|
|
|
|
|
|
if (vid != -1) return vid; /* previously computed */
|
|
|
|
a.x = c1->x;
|
|
|
|
a.y = c1->y;
|
|
|
|
a.z = c1->z;
|
|
|
|
b.x = c2->x;
|
|
|
|
b.y = c2->y;
|
|
|
|
b.z = c2->z;
|
|
|
|
|
2003-12-08 13:30:04 +00:00
|
|
|
converge(&a, &b, c1->value, c2->value, p->function, &v.position, mb, 1); /* position */
|
2002-10-12 11:37:38 +00:00
|
|
|
vnormal(&v.position, p, &v.normal);
|
|
|
|
|
|
|
|
addtovertices(&p->vertices, v); /* save vertex */
|
|
|
|
vid = p->vertices.count-1;
|
|
|
|
setedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid);
|
|
|
|
|
|
|
|
return vid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* converge: from two points of differing sign, converge to zero crossing */
|
|
|
|
/* watch it: p1 and p2 are used to calculate */
|
2003-09-05 13:54:22 +00:00
|
|
|
void converge (MB_POINT *p1, MB_POINT *p2, float v1, float v2,
|
2003-12-08 13:30:04 +00:00
|
|
|
float (*function)(float, float, float), MB_POINT *p, MetaBall *mb, int f)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
int i = 0;
|
2003-12-08 13:30:04 +00:00
|
|
|
MB_POINT pos, neg;
|
2003-09-05 13:54:22 +00:00
|
|
|
float positive = 0.0f, negative = 0.0f;
|
|
|
|
float dx = 0.0f ,dy = 0.0f ,dz = 0.0f;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2003-09-05 13:54:22 +00:00
|
|
|
if (v1 < 0) {
|
2003-12-08 13:30:04 +00:00
|
|
|
pos= *p2;
|
|
|
|
neg= *p1;
|
2003-09-05 13:54:22 +00:00
|
|
|
positive = v2;
|
|
|
|
negative = v1;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
else {
|
2003-12-08 13:30:04 +00:00
|
|
|
pos= *p1;
|
|
|
|
neg= *p2;
|
2003-09-05 13:54:22 +00:00
|
|
|
positive = v1;
|
|
|
|
negative = v2;
|
|
|
|
}
|
|
|
|
|
2003-12-08 13:30:04 +00:00
|
|
|
dx = pos.x - neg.x;
|
|
|
|
dy = pos.y - neg.y;
|
|
|
|
dz = pos.z - neg.z;
|
2003-09-05 13:54:22 +00:00
|
|
|
|
2011-04-21 05:49:47 +00:00
|
|
|
/* Approximation by linear interpolation is faster then binary subdivision,
|
2003-09-05 13:54:22 +00:00
|
|
|
* but it results sometimes (mb->thresh < 0.2) into the strange results */
|
2012-02-23 02:17:50 +00:00
|
|
|
if ((mb->thresh > 0.2f) && (f==1)) {
|
|
|
|
if ((dy == 0.0f) && (dz == 0.0f)) {
|
2003-12-08 13:30:04 +00:00
|
|
|
p->x = neg.x - negative*dx/(positive-negative);
|
|
|
|
p->y = neg.y;
|
|
|
|
p->z = neg.z;
|
2003-09-05 13:54:22 +00:00
|
|
|
return;
|
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
if ((dx == 0.0f) && (dz == 0.0f)) {
|
2003-12-08 13:30:04 +00:00
|
|
|
p->x = neg.x;
|
|
|
|
p->y = neg.y - negative*dy/(positive-negative);
|
|
|
|
p->z = neg.z;
|
2003-09-05 13:54:22 +00:00
|
|
|
return;
|
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
if ((dx == 0.0f) && (dy == 0.0f)) {
|
2003-12-08 13:30:04 +00:00
|
|
|
p->x = neg.x;
|
|
|
|
p->y = neg.y;
|
|
|
|
p->z = neg.z - negative*dz/(positive-negative);
|
2003-09-05 13:54:22 +00:00
|
|
|
return;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2003-09-05 13:54:22 +00:00
|
|
|
}
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if ((dy == 0.0f) && (dz == 0.0f)) {
|
2003-12-08 13:30:04 +00:00
|
|
|
p->y = neg.y;
|
|
|
|
p->z = neg.z;
|
2003-09-05 13:54:22 +00:00
|
|
|
while (1) {
|
|
|
|
if (i++ == RES) return;
|
2008-05-02 12:43:46 +00:00
|
|
|
p->x = 0.5f*(pos.x + neg.x);
|
2011-03-28 04:22:50 +00:00
|
|
|
if ((function(p->x,p->y,p->z)) > 0.0f) pos.x = p->x; else neg.x = p->x;
|
2003-09-05 13:54:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if ((dx == 0.0f) && (dz == 0.0f)) {
|
2003-12-08 13:30:04 +00:00
|
|
|
p->x = neg.x;
|
|
|
|
p->z = neg.z;
|
2003-09-05 13:54:22 +00:00
|
|
|
while (1) {
|
|
|
|
if (i++ == RES) return;
|
2008-05-02 12:43:46 +00:00
|
|
|
p->y = 0.5f*(pos.y + neg.y);
|
2011-03-28 04:22:50 +00:00
|
|
|
if ((function(p->x,p->y,p->z)) > 0.0f) pos.y = p->y; else neg.y = p->y;
|
2003-09-05 13:54:22 +00:00
|
|
|
}
|
2010-03-22 09:30:00 +00:00
|
|
|
}
|
2003-09-05 13:54:22 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if ((dx == 0.0f) && (dy == 0.0f)) {
|
2003-12-08 13:30:04 +00:00
|
|
|
p->x = neg.x;
|
|
|
|
p->y = neg.y;
|
2003-09-05 13:54:22 +00:00
|
|
|
while (1) {
|
|
|
|
if (i++ == RES) return;
|
2008-05-02 12:43:46 +00:00
|
|
|
p->z = 0.5f*(pos.z + neg.z);
|
2011-03-28 04:22:50 +00:00
|
|
|
if ((function(p->x,p->y,p->z)) > 0.0f) pos.z = p->z; else neg.z = p->z;
|
2003-09-05 13:54:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This is necessary to find start point */
|
2002-10-12 11:37:38 +00:00
|
|
|
while (1) {
|
2003-12-08 13:30:04 +00:00
|
|
|
p->x = 0.5f*(pos.x + neg.x);
|
|
|
|
p->y = 0.5f*(pos.y + neg.y);
|
|
|
|
p->z = 0.5f*(pos.z + neg.z);
|
2011-04-21 13:11:51 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (i++ == RES) return;
|
2003-09-05 13:54:22 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if ((function(p->x, p->y, p->z)) > 0.0f) {
|
2003-12-08 13:30:04 +00:00
|
|
|
pos.x = p->x;
|
|
|
|
pos.y = p->y;
|
|
|
|
pos.z = p->z;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2003-12-08 13:30:04 +00:00
|
|
|
neg.x = p->x;
|
|
|
|
neg.y = p->y;
|
|
|
|
neg.z = p->z;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-12-08 13:30:04 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
/* ************************************** */
|
2003-12-08 13:30:04 +00:00
|
|
|
void add_cube(PROCESS *mbproc, int i, int j, int k, int count)
|
|
|
|
{
|
|
|
|
CUBES *ncube;
|
|
|
|
int n;
|
|
|
|
int a, b, c;
|
|
|
|
|
|
|
|
/* hmmm, not only one, but eight cube will be added on the stack
|
|
|
|
* ... */
|
2012-03-24 06:18:31 +00:00
|
|
|
for (a=i-1; a<i+count; a++)
|
|
|
|
for (b=j-1; b<j+count; b++)
|
|
|
|
for (c=k-1; c<k+count; c++) {
|
2003-12-08 13:30:04 +00:00
|
|
|
/* test if cube has been found before */
|
2012-02-23 02:17:50 +00:00
|
|
|
if ( setcenter(mbproc->centers, a, b, c)==0 ) {
|
2003-12-08 13:30:04 +00:00
|
|
|
/* push cube on stack: */
|
|
|
|
ncube= (CUBES *) new_pgn_element(sizeof(CUBES));
|
|
|
|
ncube->next= mbproc->cubes;
|
|
|
|
mbproc->cubes= ncube;
|
|
|
|
|
|
|
|
ncube->cube.i= a;
|
|
|
|
ncube->cube.j= b;
|
|
|
|
ncube->cube.k= c;
|
|
|
|
|
|
|
|
/* set corners of initial cube: */
|
|
|
|
for (n = 0; n < 8; n++)
|
|
|
|
ncube->cube.corners[n] = setcorner(mbproc, a+MB_BIT(n,2), b+MB_BIT(n,1), c+MB_BIT(n,0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void find_first_points(PROCESS *mbproc, MetaBall *mb, int a)
|
|
|
|
{
|
|
|
|
MB_POINT IN, in, OUT, out; /*point;*/
|
|
|
|
MetaElem *ml;
|
|
|
|
int i, j, k, c_i, c_j, c_k;
|
|
|
|
int index[3]={1,0,-1};
|
|
|
|
float f =0.0f;
|
2011-01-17 08:31:57 +00:00
|
|
|
float in_v /*, out_v*/;
|
2008-05-02 12:43:46 +00:00
|
|
|
MB_POINT workp;
|
|
|
|
float tmp_v, workp_v, max_len, len, dx, dy, dz, nx, ny, nz, MAXN;
|
2003-12-08 13:30:04 +00:00
|
|
|
|
|
|
|
ml = mainb[a];
|
|
|
|
|
|
|
|
f = 1-(mb->thresh/ml->s);
|
|
|
|
|
|
|
|
/* Skip, when Stiffness of MetaElement is too small ... MetaElement can't be
|
|
|
|
* visible alone ... but still can influence others MetaElements :-) */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (f > 0.0f) {
|
2005-04-27 11:52:50 +00:00
|
|
|
OUT.x = IN.x = in.x= 0.0;
|
|
|
|
OUT.y = IN.y = in.y= 0.0;
|
|
|
|
OUT.z = IN.z = in.z= 0.0;
|
2003-12-08 13:30:04 +00:00
|
|
|
|
|
|
|
calc_mballco(ml, (float *)&in);
|
|
|
|
in_v = mbproc->function(in.x, in.y, in.z);
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i=0;i<3;i++) {
|
2003-12-08 13:30:04 +00:00
|
|
|
switch (ml->type) {
|
|
|
|
case MB_BALL:
|
|
|
|
OUT.x = out.x= IN.x + index[i]*ml->rad;
|
|
|
|
break;
|
|
|
|
case MB_TUBE:
|
|
|
|
case MB_PLANE:
|
|
|
|
case MB_ELIPSOID:
|
|
|
|
case MB_CUBE:
|
|
|
|
OUT.x = out.x= IN.x + index[i]*(ml->expx + ml->rad);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (j=0;j<3;j++) {
|
2003-12-08 13:30:04 +00:00
|
|
|
switch (ml->type) {
|
|
|
|
case MB_BALL:
|
|
|
|
OUT.y = out.y= IN.y + index[j]*ml->rad;
|
|
|
|
break;
|
|
|
|
case MB_TUBE:
|
|
|
|
case MB_PLANE:
|
|
|
|
case MB_ELIPSOID:
|
|
|
|
case MB_CUBE:
|
|
|
|
OUT.y = out.y= IN.y + index[j]*(ml->expy + ml->rad);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (k=0;k<3;k++) {
|
2003-12-08 13:30:04 +00:00
|
|
|
out.x = OUT.x;
|
|
|
|
out.y = OUT.y;
|
|
|
|
switch (ml->type) {
|
|
|
|
case MB_BALL:
|
|
|
|
case MB_TUBE:
|
|
|
|
case MB_PLANE:
|
|
|
|
out.z= IN.z + index[k]*ml->rad;
|
|
|
|
break;
|
|
|
|
case MB_ELIPSOID:
|
|
|
|
case MB_CUBE:
|
|
|
|
out.z= IN.z + index[k]*(ml->expz + ml->rad);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
calc_mballco(ml, (float *)&out);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2011-01-17 08:31:57 +00:00
|
|
|
/*out_v = mbproc->function(out.x, out.y, out.z);*/ /*UNUSED*/
|
2003-12-08 13:30:04 +00:00
|
|
|
|
2008-05-02 12:43:46 +00:00
|
|
|
/* find "first points" on Implicit Surface of MetaElemnt ml */
|
2008-05-08 21:33:15 +00:00
|
|
|
workp.x = in.x;
|
|
|
|
workp.y = in.y;
|
|
|
|
workp.z = in.z;
|
2008-05-02 12:43:46 +00:00
|
|
|
workp_v = in_v;
|
2011-03-28 04:22:50 +00:00
|
|
|
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));
|
2003-12-08 13:30:04 +00:00
|
|
|
|
2010-07-06 11:44:45 +00:00
|
|
|
nx = abs((out.x - in.x)/mbproc->size);
|
|
|
|
ny = abs((out.y - in.y)/mbproc->size);
|
|
|
|
nz = abs((out.z - in.z)/mbproc->size);
|
2003-12-08 13:30:04 +00:00
|
|
|
|
2008-05-02 12:43:46 +00:00
|
|
|
MAXN = MAX3(nx,ny,nz);
|
2012-02-23 02:17:50 +00:00
|
|
|
if (MAXN!=0.0f) {
|
2008-05-18 13:57:47 +00:00
|
|
|
dx = (out.x - in.x)/MAXN;
|
|
|
|
dy = (out.y - in.y)/MAXN;
|
|
|
|
dz = (out.z - in.z)/MAXN;
|
|
|
|
|
|
|
|
len = 0.0;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (len<=max_len) {
|
2008-05-18 13:57:47 +00:00
|
|
|
workp.x += dx;
|
|
|
|
workp.y += dy;
|
|
|
|
workp.z += dz;
|
|
|
|
/* compute value of implicite function */
|
|
|
|
tmp_v = mbproc->function(workp.x, workp.y, workp.z);
|
|
|
|
/* add cube to the stack, when value of implicite function crosses zero value */
|
2012-02-23 02:17:50 +00:00
|
|
|
if ((tmp_v<0.0f && workp_v>=0.0f)||(tmp_v>0.0f && workp_v<=0.0f)) {
|
2008-05-18 13:57:47 +00:00
|
|
|
|
|
|
|
/* indexes of CUBE, which includes "first point" */
|
2010-07-06 11:44:45 +00:00
|
|
|
c_i= (int)floor(workp.x/mbproc->size);
|
|
|
|
c_j= (int)floor(workp.y/mbproc->size);
|
|
|
|
c_k= (int)floor(workp.z/mbproc->size);
|
2008-05-18 13:57:47 +00:00
|
|
|
|
|
|
|
/* add CUBE (with indexes c_i, c_j, c_k) to the stack,
|
|
|
|
* this cube includes found point of Implicit Surface */
|
|
|
|
if (ml->flag & MB_NEGATIVE)
|
|
|
|
add_cube(mbproc, c_i, c_j, c_k, 2);
|
|
|
|
else
|
|
|
|
add_cube(mbproc, c_i, c_j, c_k, 1);
|
|
|
|
}
|
2011-03-28 04:22:50 +00:00
|
|
|
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));
|
2008-05-18 13:57:47 +00:00
|
|
|
workp_v = tmp_v;
|
2008-05-02 12:43:46 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2003-12-08 13:30:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2003-09-05 13:54:22 +00:00
|
|
|
void polygonize(PROCESS *mbproc, MetaBall *mb)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
CUBE c;
|
2003-12-08 13:30:04 +00:00
|
|
|
int a;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
mbproc->vertices.count = mbproc->vertices.max = 0;
|
|
|
|
mbproc->vertices.ptr = NULL;
|
|
|
|
|
|
|
|
/* allocate hash tables and build cube polygon table: */
|
|
|
|
mbproc->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers");
|
|
|
|
mbproc->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners");
|
|
|
|
mbproc->edges = MEM_callocN(2*HASHSIZE * sizeof(EDGELIST *), "mbproc->edges");
|
|
|
|
makecubetable();
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (a=0; a<totelem; a++) {
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2003-12-08 13:30:04 +00:00
|
|
|
/* try to find 8 points on the surface for each MetaElem */
|
|
|
|
find_first_points(mbproc, mb, a);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2003-12-08 13:30:04 +00:00
|
|
|
|
|
|
|
/* polygonize all MetaElems of current MetaBall */
|
2002-10-12 11:37:38 +00:00
|
|
|
while (mbproc->cubes != NULL) { /* process active cubes till none left */
|
|
|
|
c = mbproc->cubes->cube;
|
|
|
|
|
|
|
|
/* polygonize the cube directly: */
|
2003-09-05 13:54:22 +00:00
|
|
|
docube(&c, mbproc, mb);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/* pop current cube from stack */
|
|
|
|
mbproc->cubes = mbproc->cubes->next;
|
|
|
|
|
|
|
|
/* test six face directions, maybe add to stack: */
|
|
|
|
testface(c.i-1, c.j, c.k, &c, 2, LBN, LBF, LTN, LTF, mbproc);
|
|
|
|
testface(c.i+1, c.j, c.k, &c, 2, RBN, RBF, RTN, RTF, mbproc);
|
|
|
|
testface(c.i, c.j-1, c.k, &c, 1, LBN, LBF, RBN, RBF, mbproc);
|
|
|
|
testface(c.i, c.j+1, c.k, &c, 1, LTN, LTF, RTN, RTF, mbproc);
|
|
|
|
testface(c.i, c.j, c.k-1, &c, 0, LBN, LTN, RBN, RTN, mbproc);
|
|
|
|
testface(c.i, c.j, c.k+1, &c, 0, LBF, LTF, RBF, RTF, mbproc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
float init_meta(Scene *scene, Object *ob) /* return totsize */
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2010-07-13 16:06:51 +00:00
|
|
|
Scene *sce_iter= scene;
|
2002-10-12 11:37:38 +00:00
|
|
|
Base *base;
|
|
|
|
Object *bob;
|
|
|
|
MetaBall *mb;
|
|
|
|
MetaElem *ml;
|
2011-01-17 08:31:57 +00:00
|
|
|
float size, totsize, obinv[4][4], obmat[4][4], vec[3];
|
|
|
|
//float max=0.0;
|
2005-11-17 23:26:45 +00:00
|
|
|
int a, obnr, zero_size=0;
|
2012-01-11 08:51:06 +00:00
|
|
|
char obname[MAX_ID_NAME];
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
copy_m4_m4(obmat, ob->obmat); /* to cope with duplicators from next_object */
|
|
|
|
invert_m4_m4(obinv, ob->obmat);
|
2004-04-06 13:51:59 +00:00
|
|
|
a= 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2010-11-07 08:49:07 +00:00
|
|
|
BLI_split_name_num(obname, &obnr, ob->id.name+2, '.');
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2003-04-26 13:07:59 +00:00
|
|
|
/* make main array */
|
2011-02-13 10:52:18 +00:00
|
|
|
next_object(&sce_iter, 0, NULL, NULL);
|
2012-03-24 06:18:31 +00:00
|
|
|
while (next_object(&sce_iter, 1, &base, &bob)) {
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (bob->type==OB_MBALL) {
|
2005-11-17 23:26:45 +00:00
|
|
|
zero_size= 0;
|
|
|
|
ml= NULL;
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (bob==ob && (base->flag & OB_FROMDUPLI)==0) {
|
2002-10-12 11:37:38 +00:00
|
|
|
mb= ob->data;
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mb->editelems) ml= mb->editelems->first;
|
2002-10-12 11:37:38 +00:00
|
|
|
else ml= mb->elems.first;
|
|
|
|
}
|
|
|
|
else {
|
2012-01-11 08:51:06 +00:00
|
|
|
char name[MAX_ID_NAME];
|
2002-10-12 11:37:38 +00:00
|
|
|
int nr;
|
|
|
|
|
2010-11-07 08:49:07 +00:00
|
|
|
BLI_split_name_num(name, &nr, bob->id.name+2, '.');
|
2012-02-23 02:17:50 +00:00
|
|
|
if ( strcmp(obname, name)==0 ) {
|
2002-10-12 11:37:38 +00:00
|
|
|
mb= bob->data;
|
2009-01-02 19:10:35 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mb->editelems) ml= mb->editelems->first;
|
2002-10-12 11:37:38 +00:00
|
|
|
else ml= mb->elems.first;
|
|
|
|
}
|
|
|
|
}
|
2005-11-17 23:26:45 +00:00
|
|
|
|
2011-04-21 05:49:47 +00:00
|
|
|
/* when metaball object has zero scale, then MetaElem to this MetaBall
|
2005-11-17 23:26:45 +00:00
|
|
|
* will not be put to mainb array */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (bob->size[0]==0.0f || bob->size[1]==0.0f || bob->size[2]==0.0f) {
|
2005-11-17 23:26:45 +00:00
|
|
|
zero_size= 1;
|
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
else if (bob->parent) {
|
2005-11-17 23:26:45 +00:00
|
|
|
struct Object *pob=bob->parent;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (pob) {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (pob->size[0]==0.0f || pob->size[1]==0.0f || pob->size[2]==0.0f) {
|
2005-11-17 23:26:45 +00:00
|
|
|
zero_size= 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pob= pob->parent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zero_size) {
|
|
|
|
unsigned int ml_count=0;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (ml) {
|
2005-11-17 23:26:45 +00:00
|
|
|
ml_count++;
|
|
|
|
ml= ml->next;
|
|
|
|
}
|
|
|
|
totelem -= ml_count;
|
|
|
|
}
|
|
|
|
else {
|
2012-03-24 06:18:31 +00:00
|
|
|
while (ml) {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (!(ml->flag & MB_HIDE)) {
|
2005-05-30 06:37:33 +00:00
|
|
|
int i;
|
2011-01-17 08:31:57 +00:00
|
|
|
float temp1[4][4], temp2[4][4], temp3[4][4];
|
|
|
|
float (*mat)[4] = NULL, (*imat)[4] = NULL;
|
2005-05-30 06:37:33 +00:00
|
|
|
float max_x, max_y, max_z, min_x, min_y, min_z;
|
|
|
|
|
|
|
|
max_x = max_y = max_z = -3.4e38;
|
|
|
|
min_x = min_y = min_z = 3.4e38;
|
|
|
|
|
|
|
|
/* too big stiffness seems only ugly due to linear interpolation
|
|
|
|
* no need to have possibility for too big stiffness */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->s > 10.0f) ml->s = 10.0f;
|
2005-05-30 06:37:33 +00:00
|
|
|
|
2005-03-29 10:03:30 +00:00
|
|
|
/* Rotation of MetaElem is stored in quat */
|
2010-03-22 09:30:00 +00:00
|
|
|
quat_to_mat4( temp3,ml->quat);
|
2005-03-29 10:03:30 +00:00
|
|
|
|
|
|
|
/* Translation of MetaElem */
|
2009-11-10 20:43:45 +00:00
|
|
|
unit_m4(temp2);
|
2005-02-21 10:40:30 +00:00
|
|
|
temp2[3][0]= ml->x;
|
|
|
|
temp2[3][1]= ml->y;
|
|
|
|
temp2[3][2]= ml->z;
|
2005-03-29 10:03:30 +00:00
|
|
|
|
Math lib: matrix multiplication order fix for two functions that were
inconsistent with similar functions & math notation:
mul_m4_m4m4(R, B, A) => mult_m4_m4m4(R, A, B)
mul_m3_m3m4(R, B, A) => mult_m3_m3m4(R, A, B)
For branch maintainers, it should be relatively simple to fix things manually,
it's also possible run this script after merging to do automatic replacement:
http://www.pasteall.org/27459/python
2011-12-16 19:53:12 +00:00
|
|
|
mult_m4_m4m4(temp1, temp2, temp3);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2005-02-21 10:40:30 +00:00
|
|
|
/* make a copy because of duplicates */
|
|
|
|
mainb[a]= new_pgn_element(sizeof(MetaElem));
|
|
|
|
*(mainb[a])= *ml;
|
|
|
|
mainb[a]->bb = new_pgn_element(sizeof(BoundBox));
|
2005-05-30 06:37:33 +00:00
|
|
|
|
2005-02-21 10:40:30 +00:00
|
|
|
mat= new_pgn_element(4*4*sizeof(float));
|
|
|
|
imat= new_pgn_element(4*4*sizeof(float));
|
|
|
|
|
|
|
|
/* mat is the matrix to transform from mball into the basis-mball */
|
2009-11-10 20:43:45 +00:00
|
|
|
invert_m4_m4(obinv, obmat);
|
Math lib: matrix multiplication order fix for two functions that were
inconsistent with similar functions & math notation:
mul_m4_m4m4(R, B, A) => mult_m4_m4m4(R, A, B)
mul_m3_m3m4(R, B, A) => mult_m3_m3m4(R, A, B)
For branch maintainers, it should be relatively simple to fix things manually,
it's also possible run this script after merging to do automatic replacement:
http://www.pasteall.org/27459/python
2011-12-16 19:53:12 +00:00
|
|
|
mult_m4_m4m4(temp2, obinv, bob->obmat);
|
2005-02-21 10:40:30 +00:00
|
|
|
/* MetaBall transformation */
|
Math lib: matrix multiplication order fix for two functions that were
inconsistent with similar functions & math notation:
mul_m4_m4m4(R, B, A) => mult_m4_m4m4(R, A, B)
mul_m3_m3m4(R, B, A) => mult_m3_m3m4(R, A, B)
For branch maintainers, it should be relatively simple to fix things manually,
it's also possible run this script after merging to do automatic replacement:
http://www.pasteall.org/27459/python
2011-12-16 19:53:12 +00:00
|
|
|
mult_m4_m4m4(mat, temp2, temp1);
|
2011-04-21 13:11:51 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
invert_m4_m4(imat,mat);
|
2011-04-21 13:11:51 +00:00
|
|
|
|
2005-02-21 10:40:30 +00:00
|
|
|
mainb[a]->rad2= ml->rad*ml->rad;
|
2011-04-21 13:11:51 +00:00
|
|
|
|
2005-02-21 10:40:30 +00:00
|
|
|
mainb[a]->mat= (float*) mat;
|
|
|
|
mainb[a]->imat= (float*) imat;
|
2005-05-30 06:37:33 +00:00
|
|
|
|
|
|
|
/* untransformed Bounding Box of MetaElem */
|
|
|
|
/* 0 */
|
|
|
|
mainb[a]->bb->vec[0][0]= -ml->expx;
|
|
|
|
mainb[a]->bb->vec[0][1]= -ml->expy;
|
|
|
|
mainb[a]->bb->vec[0][2]= -ml->expz;
|
|
|
|
/* 1 */
|
|
|
|
mainb[a]->bb->vec[1][0]= ml->expx;
|
|
|
|
mainb[a]->bb->vec[1][1]= -ml->expy;
|
|
|
|
mainb[a]->bb->vec[1][2]= -ml->expz;
|
|
|
|
/* 2 */
|
|
|
|
mainb[a]->bb->vec[2][0]= ml->expx;
|
|
|
|
mainb[a]->bb->vec[2][1]= ml->expy;
|
|
|
|
mainb[a]->bb->vec[2][2]= -ml->expz;
|
|
|
|
/* 3 */
|
|
|
|
mainb[a]->bb->vec[3][0]= -ml->expx;
|
|
|
|
mainb[a]->bb->vec[3][1]= ml->expy;
|
|
|
|
mainb[a]->bb->vec[3][2]= -ml->expz;
|
|
|
|
/* 4 */
|
|
|
|
mainb[a]->bb->vec[4][0]= -ml->expx;
|
|
|
|
mainb[a]->bb->vec[4][1]= -ml->expy;
|
|
|
|
mainb[a]->bb->vec[4][2]= ml->expz;
|
|
|
|
/* 5 */
|
|
|
|
mainb[a]->bb->vec[5][0]= ml->expx;
|
|
|
|
mainb[a]->bb->vec[5][1]= -ml->expy;
|
|
|
|
mainb[a]->bb->vec[5][2]= ml->expz;
|
|
|
|
/* 6 */
|
|
|
|
mainb[a]->bb->vec[6][0]= ml->expx;
|
|
|
|
mainb[a]->bb->vec[6][1]= ml->expy;
|
|
|
|
mainb[a]->bb->vec[6][2]= ml->expz;
|
|
|
|
/* 7 */
|
|
|
|
mainb[a]->bb->vec[7][0]= -ml->expx;
|
|
|
|
mainb[a]->bb->vec[7][1]= ml->expy;
|
|
|
|
mainb[a]->bb->vec[7][2]= ml->expz;
|
|
|
|
|
|
|
|
/* transformation of Metalem bb */
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i=0; i<8; i++)
|
2012-04-24 22:50:49 +00:00
|
|
|
mul_m4_v3((float (*)[4])mat, mainb[a]->bb->vec[i]);
|
2005-05-30 06:37:33 +00:00
|
|
|
|
|
|
|
/* find max and min of transformed bb */
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i=0; i<8; i++) {
|
2005-05-30 06:37:33 +00:00
|
|
|
/* find maximums */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mainb[a]->bb->vec[i][0] > max_x) max_x = mainb[a]->bb->vec[i][0];
|
|
|
|
if (mainb[a]->bb->vec[i][1] > max_y) max_y = mainb[a]->bb->vec[i][1];
|
|
|
|
if (mainb[a]->bb->vec[i][2] > max_z) max_z = mainb[a]->bb->vec[i][2];
|
2005-05-30 06:37:33 +00:00
|
|
|
/* find minimums */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mainb[a]->bb->vec[i][0] < min_x) min_x = mainb[a]->bb->vec[i][0];
|
|
|
|
if (mainb[a]->bb->vec[i][1] < min_y) min_y = mainb[a]->bb->vec[i][1];
|
|
|
|
if (mainb[a]->bb->vec[i][2] < min_z) min_z = mainb[a]->bb->vec[i][2];
|
2005-02-21 10:40:30 +00:00
|
|
|
}
|
2005-05-30 06:37:33 +00:00
|
|
|
|
|
|
|
/* create "new" bb, only point 0 and 6, which are
|
2012-03-03 11:45:08 +00:00
|
|
|
* necessary for octal tree filling */
|
2005-05-30 06:37:33 +00:00
|
|
|
mainb[a]->bb->vec[0][0] = min_x - ml->rad;
|
|
|
|
mainb[a]->bb->vec[0][1] = min_y - ml->rad;
|
|
|
|
mainb[a]->bb->vec[0][2] = min_z - ml->rad;
|
|
|
|
|
|
|
|
mainb[a]->bb->vec[6][0] = max_x + ml->rad;
|
|
|
|
mainb[a]->bb->vec[6][1] = max_y + ml->rad;
|
|
|
|
mainb[a]->bb->vec[6][2] = max_z + ml->rad;
|
2005-02-21 10:40:30 +00:00
|
|
|
|
|
|
|
a++;
|
2004-06-29 17:10:13 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
ml= ml->next;
|
|
|
|
}
|
2005-11-17 23:26:45 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
}
|
2003-09-05 13:54:22 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2003-04-26 13:07:59 +00:00
|
|
|
/* totsize (= 'manhattan' radius) */
|
2002-10-12 11:37:38 +00:00
|
|
|
totsize= 0.0;
|
2012-03-24 06:18:31 +00:00
|
|
|
for (a=0; a<totelem; a++) {
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2006-06-27 09:37:12 +00:00
|
|
|
vec[0]= mainb[a]->x + mainb[a]->rad + mainb[a]->expx;
|
|
|
|
vec[1]= mainb[a]->y + mainb[a]->rad + mainb[a]->expy;
|
|
|
|
vec[2]= mainb[a]->z + mainb[a]->rad + mainb[a]->expz;
|
2004-06-29 17:10:13 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
calc_mballco(mainb[a], vec);
|
|
|
|
|
2011-11-19 01:10:05 +00:00
|
|
|
size= fabsf( vec[0] );
|
2012-02-23 02:17:50 +00:00
|
|
|
if ( size > totsize ) totsize= size;
|
2011-11-19 01:10:05 +00:00
|
|
|
size= fabsf( vec[1] );
|
2012-02-23 02:17:50 +00:00
|
|
|
if ( size > totsize ) totsize= size;
|
2011-11-19 01:10:05 +00:00
|
|
|
size= fabsf( vec[2] );
|
2012-02-23 02:17:50 +00:00
|
|
|
if ( size > totsize ) totsize= size;
|
2004-06-29 17:10:13 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
vec[0]= mainb[a]->x - mainb[a]->rad;
|
|
|
|
vec[1]= mainb[a]->y - mainb[a]->rad;
|
|
|
|
vec[2]= mainb[a]->z - mainb[a]->rad;
|
2004-06-29 17:10:13 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
calc_mballco(mainb[a], vec);
|
|
|
|
|
2011-11-19 01:10:05 +00:00
|
|
|
size= fabsf( vec[0] );
|
2012-02-23 02:17:50 +00:00
|
|
|
if ( size > totsize ) totsize= size;
|
2011-11-19 01:10:05 +00:00
|
|
|
size= fabsf( vec[1] );
|
2012-02-23 02:17:50 +00:00
|
|
|
if ( size > totsize ) totsize= size;
|
2011-11-19 01:10:05 +00:00
|
|
|
size= fabsf( vec[2] );
|
2012-02-23 02:17:50 +00:00
|
|
|
if ( size > totsize ) totsize= size;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (a=0; a<totelem; a++) {
|
2012-03-11 19:09:01 +00:00
|
|
|
thresh += densfunc(mainb[a], 2.0f * totsize, 2.0f * totsize, 2.0f * totsize);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return totsize;
|
|
|
|
}
|
|
|
|
|
2004-06-29 17:10:13 +00:00
|
|
|
/* if MetaElem lies in node, then node includes MetaElem pointer (ml_p)
|
|
|
|
* pointing at MetaElem (ml)
|
|
|
|
*/
|
|
|
|
void fill_metaball_octal_node(octal_node *node, MetaElem *ml, short i)
|
|
|
|
{
|
|
|
|
ml_pointer *ml_p;
|
|
|
|
|
|
|
|
ml_p= MEM_mallocN(sizeof(ml_pointer), "ml_pointer");
|
|
|
|
ml_p->ml= ml;
|
|
|
|
BLI_addtail(&(node->nodes[i]->elems), ml_p);
|
|
|
|
node->count++;
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->flag & MB_NEGATIVE) {
|
2004-06-29 17:10:13 +00:00
|
|
|
node->nodes[i]->neg++;
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2004-06-29 17:10:13 +00:00
|
|
|
node->nodes[i]->pos++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-09 00:41:09 +00:00
|
|
|
/* Node is subdivided as is illustrated on the following figure:
|
2004-06-29 17:10:13 +00:00
|
|
|
*
|
|
|
|
* +------+------+
|
|
|
|
* / / /|
|
|
|
|
* +------+------+ |
|
|
|
|
* / / /| +
|
|
|
|
* +------+------+ |/|
|
|
|
|
* | | | + |
|
|
|
|
* | | |/| +
|
|
|
|
* +------+------+ |/
|
|
|
|
* | | | +
|
|
|
|
* | | |/
|
|
|
|
* +------+------+
|
|
|
|
*
|
|
|
|
*/
|
2008-05-15 19:30:30 +00:00
|
|
|
void subdivide_metaball_octal_node(octal_node *node, float size_x, float size_y, float size_z, short depth)
|
2004-06-29 17:10:13 +00:00
|
|
|
{
|
|
|
|
MetaElem *ml;
|
|
|
|
ml_pointer *ml_p;
|
|
|
|
float x,y,z;
|
|
|
|
int a,i;
|
|
|
|
|
|
|
|
/* create new nodes */
|
2012-03-24 06:18:31 +00:00
|
|
|
for (a=0;a<8;a++) {
|
2004-06-29 17:10:13 +00:00
|
|
|
node->nodes[a]= MEM_mallocN(sizeof(octal_node),"octal_node");
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i=0;i<8;i++)
|
2004-06-29 17:10:13 +00:00
|
|
|
node->nodes[a]->nodes[i]= NULL;
|
|
|
|
node->nodes[a]->parent= node;
|
|
|
|
node->nodes[a]->elems.first= NULL;
|
|
|
|
node->nodes[a]->elems.last= NULL;
|
|
|
|
node->nodes[a]->count= 0;
|
|
|
|
node->nodes[a]->neg= 0;
|
|
|
|
node->nodes[a]->pos= 0;
|
|
|
|
}
|
|
|
|
|
2008-05-15 19:30:30 +00:00
|
|
|
size_x /= 2;
|
|
|
|
size_y /= 2;
|
|
|
|
size_z /= 2;
|
2004-06-29 17:10:13 +00:00
|
|
|
|
|
|
|
/* center of node */
|
2008-05-15 19:30:30 +00:00
|
|
|
node->x = x = node->x_min + size_x;
|
|
|
|
node->y = y = node->y_min + size_y;
|
|
|
|
node->z = z = node->z_min + size_z;
|
2004-06-29 17:10:13 +00:00
|
|
|
|
|
|
|
/* setting up of border points of new nodes */
|
2008-05-15 19:30:30 +00:00
|
|
|
node->nodes[0]->x_min = node->x_min;
|
|
|
|
node->nodes[0]->y_min = node->y_min;
|
|
|
|
node->nodes[0]->z_min = node->z_min;
|
|
|
|
node->nodes[0]->x = node->nodes[0]->x_min + size_x/2;
|
|
|
|
node->nodes[0]->y = node->nodes[0]->y_min + size_y/2;
|
|
|
|
node->nodes[0]->z = node->nodes[0]->z_min + size_z/2;
|
|
|
|
|
|
|
|
node->nodes[1]->x_min = x;
|
|
|
|
node->nodes[1]->y_min = node->y_min;
|
|
|
|
node->nodes[1]->z_min = node->z_min;
|
|
|
|
node->nodes[1]->x = node->nodes[1]->x_min + size_x/2;
|
|
|
|
node->nodes[1]->y = node->nodes[1]->y_min + size_y/2;
|
|
|
|
node->nodes[1]->z = node->nodes[1]->z_min + size_z/2;
|
|
|
|
|
|
|
|
node->nodes[2]->x_min = x;
|
|
|
|
node->nodes[2]->y_min = y;
|
|
|
|
node->nodes[2]->z_min = node->z_min;
|
|
|
|
node->nodes[2]->x = node->nodes[2]->x_min + size_x/2;
|
|
|
|
node->nodes[2]->y = node->nodes[2]->y_min + size_y/2;
|
|
|
|
node->nodes[2]->z = node->nodes[2]->z_min + size_z/2;
|
|
|
|
|
|
|
|
node->nodes[3]->x_min = node->x_min;
|
|
|
|
node->nodes[3]->y_min = y;
|
|
|
|
node->nodes[3]->z_min = node->z_min;
|
|
|
|
node->nodes[3]->x = node->nodes[3]->x_min + size_x/2;
|
|
|
|
node->nodes[3]->y = node->nodes[3]->y_min + size_y/2;
|
|
|
|
node->nodes[3]->z = node->nodes[3]->z_min + size_z/2;
|
|
|
|
|
|
|
|
node->nodes[4]->x_min = node->x_min;
|
|
|
|
node->nodes[4]->y_min = node->y_min;
|
|
|
|
node->nodes[4]->z_min = z;
|
|
|
|
node->nodes[4]->x = node->nodes[4]->x_min + size_x/2;
|
|
|
|
node->nodes[4]->y = node->nodes[4]->y_min + size_y/2;
|
|
|
|
node->nodes[4]->z = node->nodes[4]->z_min + size_z/2;
|
|
|
|
|
|
|
|
node->nodes[5]->x_min = x;
|
|
|
|
node->nodes[5]->y_min = node->y_min;
|
|
|
|
node->nodes[5]->z_min = z;
|
|
|
|
node->nodes[5]->x = node->nodes[5]->x_min + size_x/2;
|
|
|
|
node->nodes[5]->y = node->nodes[5]->y_min + size_y/2;
|
|
|
|
node->nodes[5]->z = node->nodes[5]->z_min + size_z/2;
|
|
|
|
|
|
|
|
node->nodes[6]->x_min = x;
|
|
|
|
node->nodes[6]->y_min = y;
|
|
|
|
node->nodes[6]->z_min = z;
|
|
|
|
node->nodes[6]->x = node->nodes[6]->x_min + size_x/2;
|
|
|
|
node->nodes[6]->y = node->nodes[6]->y_min + size_y/2;
|
|
|
|
node->nodes[6]->z = node->nodes[6]->z_min + size_z/2;
|
|
|
|
|
|
|
|
node->nodes[7]->x_min = node->x_min;
|
|
|
|
node->nodes[7]->y_min = y;
|
|
|
|
node->nodes[7]->z_min = z;
|
|
|
|
node->nodes[7]->x = node->nodes[7]->x_min + size_x/2;
|
|
|
|
node->nodes[7]->y = node->nodes[7]->y_min + size_y/2;
|
|
|
|
node->nodes[7]->z = node->nodes[7]->z_min + size_z/2;
|
2004-06-29 17:10:13 +00:00
|
|
|
|
|
|
|
ml_p= node->elems.first;
|
|
|
|
|
|
|
|
/* setting up references of MetaElems for new nodes */
|
2012-03-24 06:18:31 +00:00
|
|
|
while (ml_p) {
|
2004-06-29 17:10:13 +00:00
|
|
|
ml= ml_p->ml;
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[0][2] < z) {
|
|
|
|
if (ml->bb->vec[0][1] < y) {
|
2004-06-29 17:10:13 +00:00
|
|
|
/* vec[0][0] lies in first octant */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[0][0] < x) {
|
2004-06-29 17:10:13 +00:00
|
|
|
/* ml belongs to the (0)1st node */
|
|
|
|
fill_metaball_octal_node(node, ml, 0);
|
|
|
|
|
|
|
|
/* ml belongs to the (3)4th node */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][1] >= y) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 3);
|
|
|
|
|
|
|
|
/* ml belongs to the (7)8th node */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][2] >= z) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 7);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ml belongs to the (1)2nd node */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][0] >= x) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 1);
|
|
|
|
|
|
|
|
/* ml belongs to the (5)6th node */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][2] >= z) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ml belongs to the (2)3th node */
|
2012-02-23 02:17:50 +00:00
|
|
|
if ((ml->bb->vec[6][0] >= x) && (ml->bb->vec[6][1] >= y)) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 2);
|
|
|
|
|
|
|
|
/* ml belong to the (6)7th node */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][2] >= z) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 6);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ml belongs to the (4)5th node too */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][2] >= z) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
/* vec[0][0] is in the (1)second octant */
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2004-06-29 17:10:13 +00:00
|
|
|
/* ml belong to the (1)2nd node */
|
|
|
|
fill_metaball_octal_node(node, ml, 1);
|
|
|
|
|
|
|
|
/* ml belongs to the (2)3th node */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][1] >= y) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 2);
|
|
|
|
|
|
|
|
/* ml belongs to the (6)7th node */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][2] >= z) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 6);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ml belongs to the (5)6th node */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][2] >= z) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2004-06-29 17:10:13 +00:00
|
|
|
/* vec[0][0] is in the (3)4th octant */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[0][0] < x) {
|
2004-06-29 17:10:13 +00:00
|
|
|
/* ml belongs to the (3)4nd node */
|
|
|
|
fill_metaball_octal_node(node, ml, 3);
|
|
|
|
|
|
|
|
/* ml belongs to the (7)8th node */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][2] >= z) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 7);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ml belongs to the (2)3th node */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][0] >= x) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 2);
|
|
|
|
|
|
|
|
/* ml belongs to the (6)7th node */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][2] >= z) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vec[0][0] is in the (2)3th octant */
|
2012-02-23 02:17:50 +00:00
|
|
|
if ((ml->bb->vec[0][0] >= x) && (ml->bb->vec[0][1] >= y)) {
|
2004-06-29 17:10:13 +00:00
|
|
|
/* ml belongs to the (2)3th node */
|
|
|
|
fill_metaball_octal_node(node, ml, 2);
|
|
|
|
|
|
|
|
/* ml belongs to the (6)7th node */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][2] >= z) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[0][1] < y) {
|
2004-06-29 17:10:13 +00:00
|
|
|
/* vec[0][0] lies in (4)5th octant */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[0][0] < x) {
|
2004-06-29 17:10:13 +00:00
|
|
|
/* ml belongs to the (4)5th node */
|
|
|
|
fill_metaball_octal_node(node, ml, 4);
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][0] >= x) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 5);
|
|
|
|
}
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][1] >= y) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 7);
|
|
|
|
}
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if ((ml->bb->vec[6][0] >= x) && (ml->bb->vec[6][1] >= y)) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* vec[0][0] lies in (5)6th octant */
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 5);
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][1] >= y) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2004-06-29 17:10:13 +00:00
|
|
|
/* vec[0][0] lies in (7)8th octant */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[0][0] < x) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 7);
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ml->bb->vec[6][0] >= x) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vec[0][0] lies in (6)7th octant */
|
2012-02-23 02:17:50 +00:00
|
|
|
if ((ml->bb->vec[0][0] >= x) && (ml->bb->vec[0][1] >= y)) {
|
2004-06-29 17:10:13 +00:00
|
|
|
fill_metaball_octal_node(node, ml, 6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ml_p= ml_p->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free references of MetaElems for curent node (it is not needed anymore) */
|
|
|
|
BLI_freelistN(&node->elems);
|
|
|
|
|
|
|
|
depth--;
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (depth>0) {
|
2012-03-24 06:18:31 +00:00
|
|
|
for (a=0;a<8;a++) {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (node->nodes[a]->count > 0) /* if node is not empty, then it is subdivided */
|
2008-05-15 19:30:30 +00:00
|
|
|
subdivide_metaball_octal_node(node->nodes[a], size_x, size_y, size_z, depth);
|
2004-06-29 17:10:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free all octal nodes recursively */
|
|
|
|
void free_metaball_octal_node(octal_node *node)
|
|
|
|
{
|
|
|
|
int a;
|
2012-03-24 06:18:31 +00:00
|
|
|
for (a=0;a<8;a++) {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (node->nodes[a]!=NULL) free_metaball_octal_node(node->nodes[a]);
|
2004-06-29 17:10:13 +00:00
|
|
|
}
|
|
|
|
BLI_freelistN(&node->elems);
|
2007-04-20 12:56:51 +00:00
|
|
|
MEM_freeN(node);
|
2004-06-29 17:10:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If scene include more then one MetaElem, then octree is used */
|
|
|
|
void init_metaball_octal_tree(int depth)
|
|
|
|
{
|
|
|
|
struct octal_node *node;
|
|
|
|
ml_pointer *ml_p;
|
|
|
|
float size[3];
|
|
|
|
int a;
|
|
|
|
|
|
|
|
metaball_tree= MEM_mallocN(sizeof(octal_tree), "metaball_octal_tree");
|
|
|
|
metaball_tree->first= node= MEM_mallocN(sizeof(octal_node), "metaball_octal_node");
|
|
|
|
/* maximal depth of octree */
|
|
|
|
metaball_tree->depth= depth;
|
|
|
|
|
|
|
|
metaball_tree->neg= node->neg=0;
|
|
|
|
metaball_tree->pos= node->pos=0;
|
|
|
|
|
|
|
|
node->elems.first= NULL;
|
|
|
|
node->elems.last= NULL;
|
|
|
|
node->count=0;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (a=0;a<8;a++)
|
2004-06-29 17:10:13 +00:00
|
|
|
node->nodes[a]=NULL;
|
|
|
|
|
2007-04-20 12:56:51 +00:00
|
|
|
node->x_min= node->y_min= node->z_min= FLT_MAX;
|
|
|
|
node->x_max= node->y_max= node->z_max= -FLT_MAX;
|
2004-06-29 17:10:13 +00:00
|
|
|
|
|
|
|
/* size of octal tree scene */
|
2012-03-24 06:18:31 +00:00
|
|
|
for (a=0;a<totelem;a++) {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mainb[a]->bb->vec[0][0] < node->x_min) node->x_min= mainb[a]->bb->vec[0][0];
|
|
|
|
if (mainb[a]->bb->vec[0][1] < node->y_min) node->y_min= mainb[a]->bb->vec[0][1];
|
|
|
|
if (mainb[a]->bb->vec[0][2] < node->z_min) node->z_min= mainb[a]->bb->vec[0][2];
|
2004-06-29 17:10:13 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mainb[a]->bb->vec[6][0] > node->x_max) node->x_max= mainb[a]->bb->vec[6][0];
|
|
|
|
if (mainb[a]->bb->vec[6][1] > node->y_max) node->y_max= mainb[a]->bb->vec[6][1];
|
|
|
|
if (mainb[a]->bb->vec[6][2] > node->z_max) node->z_max= mainb[a]->bb->vec[6][2];
|
2004-06-29 17:10:13 +00:00
|
|
|
|
|
|
|
ml_p= MEM_mallocN(sizeof(ml_pointer), "ml_pointer");
|
|
|
|
ml_p->ml= mainb[a];
|
|
|
|
BLI_addtail(&node->elems, ml_p);
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (mainb[a]->flag & MB_NEGATIVE) {
|
2004-06-29 17:10:13 +00:00
|
|
|
/* number of negative MetaElem in scene */
|
|
|
|
metaball_tree->neg++;
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2004-06-29 17:10:13 +00:00
|
|
|
/* number of positive MetaElem in scene */
|
|
|
|
metaball_tree->pos++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* size of first node */
|
|
|
|
size[0]= node->x_max - node->x_min;
|
|
|
|
size[1]= node->y_max - node->y_min;
|
|
|
|
size[2]= node->z_max - node->z_min;
|
|
|
|
|
|
|
|
/* first node is subdivided recursively */
|
2008-05-15 19:30:30 +00:00
|
|
|
subdivide_metaball_octal_node(node, size[0], size[1], size[2], metaball_tree->depth);
|
2004-06-29 17:10:13 +00:00
|
|
|
}
|
|
|
|
|
2010-06-28 11:07:02 +00:00
|
|
|
void metaball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
PROCESS mbproc;
|
|
|
|
MetaBall *mb;
|
|
|
|
DispList *dl;
|
2004-11-10 13:20:13 +00:00
|
|
|
int a, nr_cubes;
|
2002-10-12 11:37:38 +00:00
|
|
|
float *ve, *no, totsize, width;
|
2010-06-27 08:35:27 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
mb= ob->data;
|
2004-11-10 13:20:13 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (totelem==0) return;
|
|
|
|
if (!(G.rendering) && (mb->flag==MB_UPDATE_NEVER)) return;
|
|
|
|
if (G.moving && mb->flag==MB_UPDATE_FAST) return;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
curindex= totindex= 0;
|
2011-02-13 10:52:18 +00:00
|
|
|
indices= NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
thresh= mb->thresh;
|
2004-04-06 13:51:59 +00:00
|
|
|
|
2004-11-10 13:20:13 +00:00
|
|
|
/* total number of MetaElems (totelem) is precomputed in find_basis_mball() function */
|
2004-04-06 13:51:59 +00:00
|
|
|
mainb= MEM_mallocN(sizeof(void *)*totelem, "mainb");
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2004-06-29 17:10:13 +00:00
|
|
|
/* initialize all mainb (MetaElems) */
|
2009-01-04 14:14:06 +00:00
|
|
|
totsize= init_meta(scene, ob);
|
2004-06-29 17:10:13 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (metaball_tree) {
|
2004-06-29 17:10:13 +00:00
|
|
|
free_metaball_octal_node(metaball_tree->first);
|
|
|
|
MEM_freeN(metaball_tree);
|
2007-04-20 12:56:51 +00:00
|
|
|
metaball_tree= NULL;
|
2004-06-29 17:10:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* if scene includes more then one MetaElem, then octal tree optimalisation is used */
|
2012-02-23 02:17:50 +00:00
|
|
|
if ((totelem > 1) && (totelem <= 64)) init_metaball_octal_tree(1);
|
|
|
|
if ((totelem > 64) && (totelem <= 128)) init_metaball_octal_tree(2);
|
|
|
|
if ((totelem > 128) && (totelem <= 512)) init_metaball_octal_tree(3);
|
|
|
|
if ((totelem > 512) && (totelem <= 1024)) init_metaball_octal_tree(4);
|
|
|
|
if (totelem > 1024) init_metaball_octal_tree(5);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2010-07-12 08:43:49 +00:00
|
|
|
/* don't polygonize metaballs with too high resolution (base mball to small)
|
|
|
|
* note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (metaball_tree) {
|
|
|
|
if ( ob->size[0] <= 0.00001f * (metaball_tree->first->x_max - metaball_tree->first->x_min) ||
|
2010-07-12 08:43:49 +00:00
|
|
|
ob->size[1] <= 0.00001f * (metaball_tree->first->y_max - metaball_tree->first->y_min) ||
|
|
|
|
ob->size[2] <= 0.00001f * (metaball_tree->first->z_max - metaball_tree->first->z_min))
|
2006-07-07 11:10:53 +00:00
|
|
|
{
|
2010-07-12 08:43:49 +00:00
|
|
|
new_pgn_element(-1); /* free values created by init_meta */
|
|
|
|
|
2006-07-07 11:10:53 +00:00
|
|
|
MEM_freeN(mainb);
|
2010-07-12 08:43:49 +00:00
|
|
|
|
|
|
|
/* free tree */
|
|
|
|
free_metaball_octal_node(metaball_tree->first);
|
|
|
|
MEM_freeN(metaball_tree);
|
|
|
|
metaball_tree= NULL;
|
|
|
|
|
2006-07-07 11:10:53 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-04-26 13:07:59 +00:00
|
|
|
/* width is size per polygonize cube */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (G.rendering) width= mb->rendersize;
|
2002-10-12 11:37:38 +00:00
|
|
|
else {
|
|
|
|
width= mb->wiresize;
|
2012-02-23 02:17:50 +00:00
|
|
|
if (G.moving && mb->flag==MB_UPDATE_HALFRES) width*= 2;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2003-04-26 13:07:59 +00:00
|
|
|
/* nr_cubes is just for safety, minimum is totsize */
|
2011-03-28 04:22:50 +00:00
|
|
|
nr_cubes= (int)(0.5f+totsize/width);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/* init process */
|
|
|
|
mbproc.function = metaball;
|
|
|
|
mbproc.size = width;
|
|
|
|
mbproc.bounds = nr_cubes;
|
2011-02-13 10:52:18 +00:00
|
|
|
mbproc.cubes= NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
mbproc.delta = width/(float)(RES*RES);
|
|
|
|
|
2003-09-05 13:54:22 +00:00
|
|
|
polygonize(&mbproc, mb);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
MEM_freeN(mainb);
|
|
|
|
|
2004-06-29 17:10:13 +00:00
|
|
|
/* free octal tree */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (totelem > 1) {
|
2004-06-29 17:10:13 +00:00
|
|
|
free_metaball_octal_node(metaball_tree->first);
|
|
|
|
MEM_freeN(metaball_tree);
|
|
|
|
metaball_tree= NULL;
|
|
|
|
}
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (curindex) {
|
2002-10-12 11:37:38 +00:00
|
|
|
dl= MEM_callocN(sizeof(DispList), "mbaldisp");
|
2010-06-28 11:07:02 +00:00
|
|
|
BLI_addtail(dispbase, dl);
|
2002-10-12 11:37:38 +00:00
|
|
|
dl->type= DL_INDEX4;
|
|
|
|
dl->nr= mbproc.vertices.count;
|
|
|
|
dl->parts= curindex;
|
|
|
|
|
|
|
|
dl->index= indices;
|
2011-02-13 10:52:18 +00:00
|
|
|
indices= NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
a= mbproc.vertices.count;
|
|
|
|
dl->verts= ve= MEM_mallocN(sizeof(float)*3*a, "mballverts");
|
|
|
|
dl->nors= no= MEM_mallocN(sizeof(float)*3*a, "mballnors");
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (a=0; a<mbproc.vertices.count; a++, no+=3, ve+=3) {
|
2002-10-12 11:37:38 +00:00
|
|
|
ve[0]= mbproc.vertices.ptr[a].position.x;
|
|
|
|
ve[1]= mbproc.vertices.ptr[a].position.y;
|
|
|
|
ve[2]= mbproc.vertices.ptr[a].position.z;
|
|
|
|
|
|
|
|
no[0]= mbproc.vertices.ptr[a].normal.x;
|
|
|
|
no[1]= mbproc.vertices.ptr[a].normal.y;
|
|
|
|
no[2]= mbproc.vertices.ptr[a].normal.z;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
freepolygonize(&mbproc);
|
|
|
|
}
|
|
|
|
|
2012-02-26 08:55:31 +00:00
|
|
|
/* basic vertex data functions */
|
|
|
|
int BKE_metaball_minmax(MetaBall *mb, float min[3], float max[3])
|
|
|
|
{
|
|
|
|
MetaElem *ml;
|
|
|
|
|
|
|
|
INIT_MINMAX(min, max);
|
|
|
|
|
|
|
|
for (ml = mb->elems.first; ml; ml = ml->next) {
|
|
|
|
DO_MINMAX(&ml->x, min, max);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (mb->elems.first != NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int BKE_metaball_center_median(MetaBall *mb, float cent[3])
|
|
|
|
{
|
|
|
|
MetaElem *ml;
|
|
|
|
int total= 0;
|
|
|
|
|
|
|
|
zero_v3(cent);
|
|
|
|
|
|
|
|
for (ml = mb->elems.first; ml; ml = ml->next) {
|
|
|
|
add_v3_v3(cent, &ml->x);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (total)
|
|
|
|
mul_v3_fl(cent, 1.0f/(float)total);
|
|
|
|
|
|
|
|
return (total != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int BKE_metaball_center_bounds(MetaBall *mb, float cent[3])
|
|
|
|
{
|
|
|
|
float min[3], max[3];
|
|
|
|
|
|
|
|
if (BKE_metaball_minmax(mb, min, max)) {
|
|
|
|
mid_v3_v3v3(cent, min, max);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_metaball_translate(MetaBall *mb, float offset[3])
|
|
|
|
{
|
|
|
|
MetaElem *ml;
|
|
|
|
|
|
|
|
for (ml = mb->elems.first; ml; ml = ml->next) {
|
|
|
|
add_v3_v3(&ml->x, offset);
|
|
|
|
}
|
|
|
|
}
|