示例#1
0
文件: mball.c 项目: mcgrathd/blender
/** \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.
 *
 * warning!, is_basis_mball() can fail on returned object, see long note above.
 */
Object *BKE_mball_basis_find(Scene *scene, Object *basis)
{
    Scene *sce_iter = scene;
    Base *base;
    Object *ob, *bob = basis;
    int basisnr, obnr;
    char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
    SceneBaseIter iter;
    EvaluationContext *eval_ctx = G.main->eval_ctx;

    BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');

    BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
    while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
        if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
            if (ob != bob) {
                BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');

                /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
                if (STREQ(obname, basisname)) {
                    if (obnr < basisnr) {
                        basis = ob;
                        basisnr = obnr;
                    }
                }
            }
        }
    }

    return basis;
}
示例#2
0
文件: mball.c 项目: mcgrathd/blender
/* \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 BKE_mball_properties_copy(Scene *scene, Object *active_object)
{
    Scene *sce_iter = scene;
    Base *base;
    Object *ob;
    MetaBall *active_mball = (MetaBall *)active_object->data;
    int basisnr, obnr;
    char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
    SceneBaseIter iter;
    EvaluationContext *eval_ctx = G.main->eval_ctx;

    BLI_split_name_num(basisname, &basisnr, active_object->id.name + 2, '.');

    BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
    while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
        if (ob->type == OB_MBALL) {
            if (ob != active_object) {
                BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');

                /* Object ob has to be in same "group" ... it means, that it has to have
                 * same base of its name */
                if (STREQ(obname, basisname)) {
                    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;
                }
            }
        }
    }
}
示例#3
0
文件: mball.c 项目: mcgrathd/blender
/* return nonzero if ob1 is a basis mball for ob */
bool BKE_mball_is_basis_for(Object *ob1, Object *ob2)
{
    int basis1nr, basis2nr;
    char basis1name[MAX_ID_NAME], basis2name[MAX_ID_NAME];

    BLI_split_name_num(basis1name, &basis1nr, ob1->id.name + 2, '.');
    BLI_split_name_num(basis2name, &basis2nr, ob2->id.name + 2, '.');

    if (STREQ(basis1name, basis2name)) {
        return BKE_mball_is_basis(ob1);
    }
    else {
        return false;
    }
}
示例#4
0
int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len)
{
	if(name[0] == '\0') {
		BLI_strncpy(name, defname, name_len);
	}

	if(unique_check(arg, name)) {
		char	tempname[UNIQUE_NAME_MAX];
		char	left[UNIQUE_NAME_MAX];
		int		number;
		int		len= BLI_split_name_num(left, &number, name, delim);
		do {
			int newlen= BLI_snprintf(tempname, name_len, "%s%c%03d", left, delim, ++number);
			if(newlen >= name_len) {
				len -= ((newlen + 1) - name_len);
				if(len < 0) len= number= 0;
				left[len]= '\0';
			}
		} while(unique_check(arg, tempname));

		BLI_strncpy(name, tempname, name_len);
		
		return 1;
	}
	
	return 0;
}
示例#5
0
int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len)
{
	if (name[0] == '\0') {
		BLI_strncpy(name, defname, name_len);
	}

	if (unique_check(arg, name)) {
		char numstr[16];
		char tempname[UNIQUE_NAME_MAX];
		char left[UNIQUE_NAME_MAX];
		int number;
		int len = BLI_split_name_num(left, &number, name, delim);
		do {
			int numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number);

			/* highly unlikely the string only has enough room for the number
			 * but support anyway */
			if ((len == 0) || (numlen >= name_len)) {
				/* number is know not to be utf-8 */
				BLI_strncpy(tempname, numstr, name_len);
			}
			else {
				char *tempname_buf;
				tempname[0] = '\0';
				tempname_buf = BLI_strncat_utf8(tempname, left, name_len - numlen);
				memcpy(tempname_buf, numstr, numlen + 1);
			}
		} while (unique_check(arg, tempname));

		BLI_strncpy(name, tempname, name_len);
		
		return 1;
	}
	
	return 0;
}
示例#6
0
static int check_for_dupid(ListBase *lb, ID *id, char *name)
{
	ID *idtest;
	int nr= 0, nrtest, a, left_len;
	char left[32], leftest[32], in_use[32];

	/* make sure input name is terminated properly */
	/* if( strlen(name) > 21 ) name[21]= 0; */
	/* removed since this is only ever called from one place - campbell */

	while (1) {

		/* phase 1: id already exists? */
		idtest = is_dupid(lb, id, name);

		/* if there is no double, done */
		if( idtest == NULL ) return 0;

		/* we have a dup; need to make a new name */
		/* quick check so we can reuse one of first 32 ids if vacant */
		memset(in_use, 0, sizeof(in_use));

		/* get name portion, number portion ("name.number") */
		left_len= BLI_split_name_num(left, &nr, name, '.');

		/* if new name will be too long, truncate it */
		if(nr > 999 && left_len > 16) {
			left[16]= 0;
			left_len= 16;
		}
		else if(left_len > 17) {
			left[17]= 0;
			left_len= 17;
		}

		for(idtest= lb->first; idtest; idtest= idtest->next) {
			if(		(id != idtest) &&
					(idtest->lib == NULL) &&
					(*name == *(idtest->name+2)) &&
					(strncmp(name, idtest->name+2, left_len)==0) &&
					(BLI_split_name_num(leftest, &nrtest, idtest->name+2, '.') == left_len)
			) {
				if(nrtest < sizeof(in_use))
					in_use[nrtest]= 1;	/* mark as used */
				if(nr <= nrtest)
					nr= nrtest+1;		/* track largest unused */
			}
		}

		/* decide which value of nr to use */
		for(a=0; a < sizeof(in_use); a++) {
			if(a>=nr) break;	/* stop when we've check up to biggest */
			if( in_use[a]==0 ) { /* found an unused value */
				nr = a;
				break;
			}
		}

		/* If the original name has no numeric suffix, 
		 * rather than just chopping and adding numbers, 
		 * shave off the end chars until we have a unique name.
		 * Check the null terminators match as well so we dont get Cube.000 -> Cube.00 */
		if (nr==0 && name[left_len]== '\0') {
			int len = left_len-1;
			idtest= is_dupid(lb, id, name);
			
			while (idtest && len> 1) {
				name[len--] = '\0';
				idtest= is_dupid(lb, id, name);
			}
			if (idtest == NULL) return 1;
			/* otherwise just continue and use a number suffix */
		}
		
		if(nr > 999 && left_len > 16) {
			/* this would overflow name buffer */
			left[16] = 0;
			/* left_len = 16; */ /* for now this isnt used again */
			memcpy(name, left, sizeof(char) * 17);
			continue;
		}
		/* this format specifier is from hell... */
		BLI_snprintf(name, sizeof(id->name) - 2,"%s.%.3d", left, nr);

		return 1;
	}
}
示例#7
0
static bool check_for_dupid(ListBase *lb, ID *id, char *name)
{
	ID *idtest;
	int nr = 0, a, left_len;
#define MAX_IN_USE 64
	bool in_use[MAX_IN_USE];
	/* to speed up finding unused numbers within [1 .. MAX_IN_USE - 1] */

	char left[MAX_ID_NAME + 8], leftest[MAX_ID_NAME + 8];

	while (true) {

		/* phase 1: id already exists? */
		idtest = is_dupid(lb, id, name);

		/* if there is no double, done */
		if (idtest == NULL) return false;

		/* we have a dup; need to make a new name */
		/* quick check so we can reuse one of first MAX_IN_USE - 1 ids if vacant */
		memset(in_use, false, sizeof(in_use));

		/* get name portion, number portion ("name.number") */
		left_len = BLI_split_name_num(left, &nr, name, '.');

		/* if new name will be too long, truncate it */
		if (nr > 999 && left_len > (MAX_ID_NAME - 8)) {  /* assumption: won't go beyond 9999 */
			left[MAX_ID_NAME - 8] = 0;
			left_len = MAX_ID_NAME - 8;
		}
		else if (left_len > (MAX_ID_NAME - 7)) {
			left[MAX_ID_NAME - 7] = 0;
			left_len = MAX_ID_NAME - 7;
		}

		for (idtest = lb->first; idtest; idtest = idtest->next) {
			int nrtest;
			if ( (id != idtest) &&
			     (idtest->lib == NULL) &&
			     (*name == *(idtest->name + 2)) &&
			     (strncmp(name, idtest->name + 2, left_len) == 0) &&
			     (BLI_split_name_num(leftest, &nrtest, idtest->name + 2, '.') == left_len)
			     )
			{
				/* will get here at least once, otherwise is_dupid call above would have returned NULL */
				if (nrtest < MAX_IN_USE)
					in_use[nrtest] = true;  /* mark as used */
				if (nr <= nrtest)
					nr = nrtest + 1;    /* track largest unused */
			}
		}
		/* At this point, 'nr' will typically be at least 1. (but not always) */
		// BLI_assert(nr >= 1);

		/* decide which value of nr to use */
		for (a = 0; a < MAX_IN_USE; a++) {
			if (a >= nr) break;  /* stop when we've checked up to biggest */  /* redundant check */
			if (!in_use[a]) { /* found an unused value */
				nr = a;
				/* can only be zero if all potential duplicate names had
				 * nonzero numeric suffixes, which means name itself has
				 * nonzero numeric suffix (else no name conflict and wouldn't
				 * have got here), which means name[left_len] is not a null */
				break;
			}
		}
		/* At this point, nr is either the lowest unused number within [0 .. MAX_IN_USE - 1],
		 * or 1 greater than the largest used number if all those low ones are taken.
		 * We can't be bothered to look for the lowest unused number beyond (MAX_IN_USE - 1). */

		/* If the original name has no numeric suffix, 
		 * rather than just chopping and adding numbers, 
		 * shave off the end chars until we have a unique name.
		 * Check the null terminators match as well so we don't get Cube.000 -> Cube.00 */
		if (nr == 0 && name[left_len] == '\0') {
			int len;
			/* FIXME: this code will never be executed, because either nr will be
			 * at least 1, or name will not end at left_len! */
			BLI_assert(0);

			len = left_len - 1;
			idtest = is_dupid(lb, id, name);
			
			while (idtest && len > 1) {
				name[len--] = '\0';
				idtest = is_dupid(lb, id, name);
			}
			if (idtest == NULL) return true;
			/* otherwise just continue and use a number suffix */
		}
		
		if (nr > 999 && left_len > (MAX_ID_NAME - 8)) {
			/* this would overflow name buffer */
			left[MAX_ID_NAME - 8] = 0;
			/* left_len = MAX_ID_NAME - 8; */ /* for now this isn't used again */
			memcpy(name, left, sizeof(char) * (MAX_ID_NAME - 7));
			continue;
		}
		/* this format specifier is from hell... */
		BLI_snprintf(name, sizeof(id->name) - 2, "%s.%.3d", left, nr);

		return true;
	}

#undef MAX_IN_USE
}
/**
 * Iterates over ALL objects in the scene and all of its sets, including
 * making all duplis(not only metas). Copies metas to mainb array.
 * Computes bounding boxes for building BVH. */
static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob)
{
	Scene *sce_iter = scene;
	Base *base;
	Object *bob;
	MetaBall *mb;
	const MetaElem *ml;
	float obinv[4][4], obmat[4][4];
	unsigned int i;
	int obnr, zero_size = 0;
	char obname[MAX_ID_NAME];
	SceneBaseIter iter;

	copy_m4_m4(obmat, ob->obmat);   /* to cope with duplicators from BKE_scene_base_iter_next */
	invert_m4_m4(obinv, ob->obmat);

	BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');

	/* make main array */
	BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
	while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &bob)) {
		if (bob->type == OB_MBALL) {
			zero_size = 0;
			ml = NULL;

			if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) {
				mb = ob->data;

				if (mb->editelems) ml = mb->editelems->first;
				else ml = mb->elems.first;
			}
			else {
				char name[MAX_ID_NAME];
				int nr;

				BLI_split_name_num(name, &nr, bob->id.name + 2, '.');
				if (STREQ(obname, name)) {
					mb = bob->data;

					if (mb->editelems) ml = mb->editelems->first;
					else ml = mb->elems.first;
				}
			}

			/* when metaball object has zero scale, then MetaElem to this MetaBall
			 * will not be put to mainb array */
			if (has_zero_axis_m4(bob->obmat)) {
				zero_size = 1;
			}
			else if (bob->parent) {
				struct Object *pob = bob->parent;
				while (pob) {
					if (has_zero_axis_m4(pob->obmat)) {
						zero_size = 1;
						break;
					}
					pob = pob->parent;
				}
			}

			if (zero_size) {
				while (ml) {
					ml = ml->next;
				}
			}
			else {
				while (ml) {
					if (!(ml->flag & MB_HIDE)) {
						float pos[4][4], rot[4][4];
						float expx, expy, expz;
						float tempmin[3], tempmax[3];

						MetaElem *new_ml;

						/* make a copy because of duplicates */
						new_ml = BLI_memarena_alloc(process->pgn_elements, sizeof(MetaElem));
						*(new_ml) = *ml;
						new_ml->bb = BLI_memarena_alloc(process->pgn_elements, sizeof(BoundBox));
						new_ml->mat = BLI_memarena_alloc(process->pgn_elements, 4 * 4 * sizeof(float));
						new_ml->imat = BLI_memarena_alloc(process->pgn_elements, 4 * 4 * sizeof(float));

						/* too big stiffness seems only ugly due to linear interpolation
						* no need to have possibility for too big stiffness */
						if (ml->s > 10.0f) new_ml->s = 10.0f;
						else new_ml->s = ml->s;

						/* if metaball is negative, set stiffness negative */
						if (new_ml->flag & MB_NEGATIVE) new_ml->s = -new_ml->s;

						/* Translation of MetaElem */
						unit_m4(pos);
						pos[3][0] = ml->x;
						pos[3][1] = ml->y;
						pos[3][2] = ml->z;

						/* Rotation of MetaElem is stored in quat */
						quat_to_mat4(rot, ml->quat);

						/* basis object space -> world -> ml object space -> position -> rotation -> ml local space */
						mul_m4_series((float(*)[4])new_ml->mat, obinv, bob->obmat, pos, rot);
						/* ml local space -> basis object space */
						invert_m4_m4((float(*)[4])new_ml->imat, (float(*)[4])new_ml->mat);

						/* rad2 is inverse of squared radius */
						new_ml->rad2 = 1 / (ml->rad * ml->rad);

						/* initial dimensions = radius */
						expx = ml->rad;
						expy = ml->rad;
						expz = ml->rad;

						switch (ml->type) {
							case MB_BALL:
								break;
							case MB_CUBE: /* cube is "expanded" by expz, expy and expx */
								expz += ml->expz;
								/* fall through */
							case MB_PLANE: /* plane is "expanded" by expy and expx */
								expy += ml->expy;
								/* fall through */
							case MB_TUBE: /* tube is "expanded" by expx */
								expx += ml->expx;
								break;
							case MB_ELIPSOID: /* ellipsoid is "stretched" by exp* */
								expx *= ml->expx;
								expy *= ml->expy;
								expz *= ml->expz;
								break;
						}

						/* untransformed Bounding Box of MetaElem */
						/* TODO, its possible the elem type has been changed and the exp* values can use a fallback */
						copy_v3_fl3(new_ml->bb->vec[0], -expx, -expy, -expz);  /* 0 */
						copy_v3_fl3(new_ml->bb->vec[1], +expx, -expy, -expz);  /* 1 */
						copy_v3_fl3(new_ml->bb->vec[2], +expx, +expy, -expz);  /* 2 */
						copy_v3_fl3(new_ml->bb->vec[3], -expx, +expy, -expz);  /* 3 */
						copy_v3_fl3(new_ml->bb->vec[4], -expx, -expy, +expz);  /* 4 */
						copy_v3_fl3(new_ml->bb->vec[5], +expx, -expy, +expz);  /* 5 */
						copy_v3_fl3(new_ml->bb->vec[6], +expx, +expy, +expz);  /* 6 */
						copy_v3_fl3(new_ml->bb->vec[7], -expx, +expy, +expz);  /* 7 */

						/* transformation of Metalem bb */
						for (i = 0; i < 8; i++)
							mul_m4_v3((float(*)[4])new_ml->mat, new_ml->bb->vec[i]);

						/* find max and min of transformed bb */
						INIT_MINMAX(tempmin, tempmax);
						for (i = 0; i < 8; i++) {
							DO_MINMAX(new_ml->bb->vec[i], tempmin, tempmax);
						}

						/* set only point 0 and 6 - AABB of Metaelem */
						copy_v3_v3(new_ml->bb->vec[0], tempmin);
						copy_v3_v3(new_ml->bb->vec[6], tempmax);

						/* add new_ml to mainb[] */
						if (UNLIKELY(process->totelem == process->mem)) {
							process->mem = process->mem * 2 + 10;
							process->mainb = MEM_reallocN(process->mainb, sizeof(MetaElem *) * process->mem);
						}
						process->mainb[process->totelem++] = new_ml;
					}
					ml = ml->next;
				}
			}
		}
	}

	/* compute AABB of all Metaelems */
	if (process->totelem > 0) {
		copy_v3_v3(process->allbb.min, process->mainb[0]->bb->vec[0]);
		copy_v3_v3(process->allbb.max, process->mainb[0]->bb->vec[6]);
		for (i = 1; i < process->totelem; i++)
			make_box_union(process->mainb[i]->bb, &process->allbb, &process->allbb);
	}
}