[Bf-blender-cvs] [c71768d] gooseberry: Alternative dupli generator function for creating duplis in a group without a specific parent.

Lukas Tönne noreply at git.blender.org
Mon Mar 23 13:03:28 CET 2015


Commit: c71768d86432ee1151ac1085055066e461adbc39
Author: Lukas Tönne
Date:   Fri Mar 13 16:40:50 2015 +0100
Branches: gooseberry
https://developer.blender.org/rBc71768d86432ee1151ac1085055066e461adbc39

Alternative dupli generator function for creating duplis in a group
without a specific parent.

===================================================================

M	source/blender/blenkernel/BKE_anim.h
M	source/blender/blenkernel/intern/group.c
M	source/blender/blenkernel/intern/object_dupli.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h
index 4f3f6e2..6d4eb1b 100644
--- a/source/blender/blenkernel/BKE_anim.h
+++ b/source/blender/blenkernel/BKE_anim.h
@@ -71,8 +71,10 @@ int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], fl
 /* ---------------------------------------------------- */
 /* Dupli-Geometry */
 
-struct ListBase *object_duplilist_ex(struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob, bool update);
-struct ListBase *object_duplilist(struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob);
+struct ListBase *object_duplilist_ex(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, bool update);
+struct ListBase *object_duplilist(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+struct ListBase *group_duplilist_ex(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Group *group, bool update);
+struct ListBase *group_duplilist(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Group *group);
 void free_object_duplilist(struct ListBase *lb);
 int count_duplilist(struct Object *ob);
 
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index f3869e4..f24eab8 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -327,7 +327,7 @@ bool BKE_group_is_animated(Group *group, Object *UNUSED(parent))
 	GroupObject *go;
 
 #if 0 /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */
-	if (parent->nlastrips.first)
+	if (parent && parent->nlastrips.first)
 		return 1;
 #endif
 
@@ -394,7 +394,7 @@ void BKE_group_handle_recalc_and_update(EvaluationContext *eval_ctx, Scene *scen
 	   * but when its enabled at some point it will need to be changed so as not to update so much - campbell */
 
 	/* if animated group... */
-	if (parent->nlastrips.first) {
+	if (parent && parent->nlastrips.first) {
 		int cfrao;
 		
 		/* switch to local time */
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 636c554..bcdd3ab 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -99,7 +99,7 @@ typedef struct DupliGenerator {
 static const DupliGenerator *get_dupli_generator(const DupliContext *ctx);
 
 /* create initial context for root object */
-static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], bool update)
+static void init_context_ex(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], const DupliGenerator *gen, bool update)
 {
 	r_ctx->eval_ctx = eval_ctx;
 	r_ctx->scene = scene;
@@ -113,14 +113,19 @@ static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene
 		copy_m4_m4(r_ctx->space_mat, space_mat);
 	else
 		unit_m4(r_ctx->space_mat);
-	r_ctx->lay = ob->lay;
+	r_ctx->lay = ob ? ob->lay : 0;
 	r_ctx->level = 0;
 
-	r_ctx->gen = get_dupli_generator(r_ctx);
+	r_ctx->gen = gen ? gen : get_dupli_generator(r_ctx);
 
 	r_ctx->duplilist = NULL;
 }
 
+static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update)
+{
+	init_context_ex(r_ctx, eval_ctx, scene, ob, NULL, NULL, update);
+}
+
 /* create sub-context for recursive duplis */
 static void copy_dupli_context(DupliContext *r_ctx, const DupliContext *ctx, Object *ob, float mat[4][4], int index, bool animated)
 {
@@ -129,7 +134,7 @@ static void copy_dupli_context(DupliContext *r_ctx, const DupliContext *ctx, Obj
 	r_ctx->animated |= animated; /* object animation makes all children animated */
 
 	/* XXX annoying, previously was done by passing an ID* argument, this at least is more explicit */
-	if (ctx->gen->type == OB_DUPLIGROUP)
+	if (ctx->gen->type == OB_DUPLIGROUP && ctx->object)
 		r_ctx->group = ctx->object->dup_group;
 
 	r_ctx->object = ob;
@@ -222,7 +227,10 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
 {
 	Object *parent = ctx->object;
 	Object *obedit = ctx->scene->obedit;
-
+	
+	if (!parent)
+		return;
+	
 	if (ctx->group) {
 		unsigned int lay = ctx->group->layer;
 		GroupObject *go;
@@ -258,69 +266,84 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
 
 /*---- Implementations ----*/
 
-/* OB_DUPLIGROUP */
-static void make_duplis_group(const DupliContext *ctx)
+/* Intern function for creating instances of group content
+ * with or without a parent (parent == NULL is allowed!)
+ * Note: some of the group animation update functions use the parent object,
+ * but this is old NLA code that is currently disabled and might be removed entirely.
+ */
+static void make_duplis_group_intern(const DupliContext *ctx, Group *group, Object *parent)
 {
-	bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER);
-	Object *ob = ctx->object;
-	Group *group;
+	const bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER);
+	
 	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 */
+	bool animated;
+	
 	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. */
-
+	
+	if (parent) {
+		/* combine group offset and obmat */
+		mul_m4_m4m4(group_mat, parent->obmat, group_mat);
+		/* don't access 'parent->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);
+		BKE_group_handle_recalc_and_update(ctx->eval_ctx, ctx->scene, parent, group);
 	}
-
-	animated = BKE_group_is_animated(group, ob);
-
+	
+	animated = BKE_group_is_animated(group, parent);
+	
 	for (go = group->gobject.first, id = 0; go; go = go->next, id++) {
+		float mat[4][4];
+		bool hide;
+		
 		/* 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);
+		if (go->ob == parent)
+			continue;
+		
+		/* 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);
 	}
 }
 
+/* OB_DUPLIGROUP */
+static void make_duplis_group(const DupliContext *ctx)
+{
+	Object *ob = ctx->object;
+	if (!ob || !ob->dup_group)
+		return;
+	
+	make_duplis_group_intern(ctx, ob->dup_group, ob);
+}
+
 const DupliGenerator gen_dupli_group = {
     OB_DUPLIGROUP,                  /* type */
     make_duplis_group               /* make_duplis */
@@ -334,8 +357,9 @@ static void make_duplis_frames(const DupliContext *ctx)
 	extern int enable_cu_speed; /* object.c */
 	Object copyob;
 	int cfrao = scene->r.cfra;
-	int dupend = ob->dupend;
 
+	if (!ob)
+		return;
 	/* dupliframes not supported inside groups */
 	if (ctx->group)
 		return;
@@ -344,7 +368,7 @@ static void make_duplis_frames(const DupliContext *ctx)
 	 */
 	if (ob->parent == NULL && BLI_listbase_is_empty(&ob->constraints) && ob->adt == NULL)
 		return;
-
+	
 	/* make a copy of the object's original data (before any dupli-data overwrites it)
 	 * as we'll need this to keep track of unkeyed data
 	 *	- this doesn't take into account other data that can be reached from the object,
@@ -359,7 +383,7 @@ static void make_duplis_frames(const DupliContext *ctx)
 	 * updates, as this is not a permanent change to the object */
 	ob->id.flag |= LIB_ANIM_NO_RECALC;
 
-	for (scene->r.cfra = ob->dupsta; scene->r.cfra <= dupend; scene->r.cfra++) {
+	for (scene->r.cfra = ob->dupsta; scene->r.cfra <= ob->dupend; scene->r.cfra++) {
 		int ok = 1;
 
 		/* - dupoff = how often a frames within the range shouldn't be made into duplis
@@ -515

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list