コード例 #1
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;
                }
            }
        }
    }
}
コード例 #2
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;
}
コード例 #3
0
/**
 * 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);
	}
}