Beispiel #1
0
static void vertex_dupli__mapFunc(void *userData, int index, const float co[3],
                                  const float nor_f[3], const short nor_s[3])
{
	const VertexDupliData *vdd = userData;
	Object *inst_ob = vdd->inst_ob;
	DupliObject *dob;
	float obmat[4][4], space_mat[4][4];

	/* obmat is transform to vertex */
	get_duplivert_transform(co, nor_f, nor_s, vdd->use_rotation, inst_ob->trackflag, inst_ob->upflag, obmat);
	/* make offset relative to inst_ob using relative child transform */
	mul_mat3_m4_v3((float (*)[4])vdd->child_imat, obmat[3]);
	/* apply obmat _after_ the local vertex transform */
	mul_m4_m4m4(obmat, inst_ob->obmat, obmat);

	/* space matrix is constructed by removing obmat transform,
	 * this yields the worldspace transform for recursive duplis
	 */
	mul_m4_m4m4(space_mat, obmat, inst_ob->imat);

	dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index, false, false);

	if (vdd->orco)
		copy_v3_v3(dob->orco, vdd->orco[index]);

	/* recursion */
	make_recursive_duplis(vdd->ctx, vdd->inst_ob, space_mat, index, false);
}
Beispiel #2
0
/* OB_DUPLIGROUP */
static void make_duplis_group(const DupliContext *ctx)
{
	bool for_render = ctx->eval_ctx->for_render;
	Object *ob = ctx->object;
	Group *group;
	GroupObject *go;
	float group_mat[4][4];
	int id;
	bool animated, hide;

	if (ob->dup_group == NULL) return;
	group = ob->dup_group;

	/* combine group offset and obmat */
	unit_m4(group_mat);
	sub_v3_v3(group_mat[3], group->dupli_ofs);
	mul_m4_m4m4(group_mat, ob->obmat, group_mat);
	/* don't access 'ob->obmat' from now on. */

	/* handles animated groups */

	/* we need to check update for objects that are not in scene... */
	if (ctx->do_update) {
		/* note: update is optional because we don't always need object
		 * transformations to be correct. Also fixes bug [#29616]. */
		BKE_group_handle_recalc_and_update(ctx->eval_ctx, ctx->scene, ob, group);
	}

	animated = BKE_group_is_animated(group, ob);

	for (go = group->gobject.first, id = 0; go; go = go->next, id++) {
		/* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
		if (go->ob != ob) {
			float mat[4][4];

			/* group dupli offset, should apply after everything else */
			mul_m4_m4m4(mat, group_mat, go->ob->obmat);

			/* check the group instance and object layers match, also that the object visible flags are ok. */
			hide = (go->ob->lay & group->layer) == 0 ||
			       (for_render ? go->ob->restrictflag & OB_RESTRICT_RENDER : go->ob->restrictflag & OB_RESTRICT_VIEW);

			make_dupli(ctx, go->ob, mat, id, animated, hide);

			/* recursion */
			make_recursive_duplis(ctx, go->ob, group_mat, id, animated);
		}
	}
}
Beispiel #3
0
static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Object *inst_ob)
{
	FaceDupliData *fdd = userdata;
	MPoly *mpoly = fdd->mpoly, *mp;
	MLoop *mloop = fdd->mloop;
	MVert *mvert = fdd->mvert;
	float (*orco)[3] = fdd->orco;
	MLoopUV *mloopuv = fdd->mloopuv;
	int a, totface = fdd->totface;
	bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW);
	float child_imat[4][4];
	DupliObject *dob;

	invert_m4_m4(inst_ob->imat, inst_ob->obmat);
	/* relative transform from parent to child space */
	mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat);

	for (a = 0, mp = mpoly; a < totface; a++, mp++) {
		MLoop *loopstart = mloop + mp->loopstart;
		float space_mat[4][4], obmat[4][4];

		if (UNLIKELY(mp->totloop < 3))
			continue;

		/* obmat is transform to face */
		get_dupliface_transform(mp, loopstart, mvert, fdd->use_scale, ctx->object->dupfacesca, obmat);
		/* make offset relative to inst_ob using relative child transform */
		mul_mat3_m4_v3(child_imat, obmat[3]);

		/* XXX ugly hack to ensure same behavior as in master
		 * this should not be needed, parentinv is not consistent
		 * outside of parenting.
		 */
		{
			float imat[3][3];
			copy_m3_m4(imat, inst_ob->parentinv);
			mul_m4_m3m4(obmat, imat, obmat);
		}

		/* apply obmat _after_ the local face transform */
		mul_m4_m4m4(obmat, inst_ob->obmat, obmat);

		/* space matrix is constructed by removing obmat transform,
		 * this yields the worldspace transform for recursive duplis
		 */
		mul_m4_m4m4(space_mat, obmat, inst_ob->imat);

		dob = make_dupli(ctx, inst_ob, obmat, a, false, false);
		if (use_texcoords) {
			float w = 1.0f / (float)mp->totloop;

			if (orco) {
				int j;
				for (j = 0; j < mp->totloop; j++) {
					madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w);
				}
			}

			if (mloopuv) {
				int j;
				for (j = 0; j < mp->totloop; j++) {
					madd_v2_v2fl(dob->uv, mloopuv[mp->loopstart + j].uv, w);
				}
			}
		}

		/* recursion */
		make_recursive_duplis(ctx, inst_ob, space_mat, a, false);
	}
}
Beispiel #4
0
/* OB_DUPLIGROUP */
static void make_duplis_group(const DupliContext *ctx)
{
	bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER);
	Object *ob = ctx->object;
	Group *group;
	GroupObject *go;
	float group_mat[4][4];
	int id;
	bool animated, hide;

	if (ob->dup_group == NULL) return;
	group = ob->dup_group;

	/* combine group offset and obmat */
	unit_m4(group_mat);
	sub_v3_v3(group_mat[3], group->dupli_ofs);
	mul_m4_m4m4(group_mat, ob->obmat, group_mat);
	/* don't access 'ob->obmat' from now on. */

	/* handles animated groups */

	/* we need to check update for objects that are not in scene... */
	if (ctx->do_update) {
		/* note: update is optional because we don't always need object
		 * transformations to be correct. Also fixes bug [#29616]. */
		BKE_group_handle_recalc_and_update(ctx->eval_ctx, ctx->scene, ob, group);
	}

	animated = BKE_group_is_animated(group, ob);

	for (go = group->gobject.first, id = 0; go; go = go->next, id++) {
		/* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
		if (go->ob != ob) {
			float mat[4][4];

			/* Special case for instancing dupli-groups, see: T40051
			 * this object may be instanced via dupli-verts/faces, in this case we don't want to render
			 * (blender convention), but _do_ show in the viewport.
			 *
			 * Regular objects work fine but not if we're instancing dupli-groups,
			 * because the rules for rendering aren't applied to objects they instance.
			 * We could recursively pass down the 'hide' flag instead, but that seems unnecessary.
			 */
			if (for_render && go->ob->parent && go->ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES)) {
				continue;
			}

			/* group dupli offset, should apply after everything else */
			mul_m4_m4m4(mat, group_mat, go->ob->obmat);

			/* check the group instance and object layers match, also that the object visible flags are ok. */
			hide = (go->ob->lay & group->layer) == 0 ||
			       (for_render ? go->ob->restrictflag & OB_RESTRICT_RENDER : go->ob->restrictflag & OB_RESTRICT_VIEW);

			make_dupli(ctx, go->ob, mat, id, animated, hide);

			/* recursion */
			make_recursive_duplis(ctx, go->ob, group_mat, id, animated);
		}
	}
}