Fix T41010: MetaBall Duplivert Unwanted Movement Bug.

BKE_scene_base_iter_next() was completely messing poor dupli objects' matrices...

Note this func should be reworked, but as stated in comments, it should not exist at all,
DAG should be used here, so until we have new shinny one we can live with this.

Also, mballs do not behave correctly when used as duplis (org object remains visible/rendered,
unlike any other object type). This will be fixed in a separate patch/commit,
since it proved to be rather tricky to handle.
This commit is contained in:
Bastien Montagne 2014-07-18 22:31:33 +02:00
parent a474125893
commit e0d8e62f2b
Notes: blender-bot 2023-02-14 10:22:23 +01:00
Referenced by issue #43666, Emitted Metaball not showing and rendering correctly
Referenced by issue #43666, Emitted Metaball not showing and rendering correctly
Referenced by issue #41226, Wrong Undo on curves
Referenced by issue #41128, Box selection bug with armatures
Referenced by issue #41123, Add Transparent Shader to Mix Shader with Material Panel open equals crash - OSL segtfault?
Referenced by issue #41010, MetaBall Duplivert Unwanted Movement Bug
2 changed files with 25 additions and 13 deletions

View File

@ -84,6 +84,7 @@ typedef struct SceneBaseIter {
struct ListBase *duplilist;
struct DupliObject *dupob;
float omat[4][4];
struct Object *dupli_refob;
int phase;
} SceneBaseIter;

View File

@ -804,9 +804,7 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)
BKE_libblock_free(bmain, sce);
}
/* used by metaballs
* doesn't return the original duplicated object, only dupli's
*/
/* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */
int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
Scene **scene, int val, Base **base, Object **ob)
{
@ -817,11 +815,12 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
iter->phase = F_START;
iter->dupob = NULL;
iter->duplilist = NULL;
iter->dupli_refob = NULL;
}
else {
/* run_again is set when a duplilist has been ended */
while (run_again) {
run_again = 0;
run_again = false;
/* the first base */
if (iter->phase == F_START) {
@ -879,34 +878,46 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
iter->dupob = iter->duplilist->first;
if (!iter->dupob)
if (!iter->dupob) {
free_object_duplilist(iter->duplilist);
iter->duplilist = NULL;
}
iter->dupli_refob = NULL;
}
}
}
/* handle dupli's */
if (iter->dupob) {
copy_m4_m4(iter->omat, iter->dupob->ob->obmat);
copy_m4_m4(iter->dupob->ob->obmat, iter->dupob->mat);
(*base)->flag |= OB_FROMDUPLI;
*ob = iter->dupob->ob;
iter->phase = F_DUPLI;
if (iter->dupli_refob != *ob) {
if (iter->dupli_refob) {
/* Restore previous object's real matrix. */
copy_m4_m4(iter->dupli_refob->obmat, iter->omat);
}
/* Backup new object's real matrix. */
iter->dupli_refob = *ob;
copy_m4_m4(iter->omat, iter->dupli_refob->obmat);
}
copy_m4_m4((*ob)->obmat, iter->dupob->mat);
iter->dupob = iter->dupob->next;
}
else if (iter->phase == F_DUPLI) {
iter->phase = F_SCENE;
(*base)->flag &= ~OB_FROMDUPLI;
for (iter->dupob = iter->duplilist->first; iter->dupob; iter->dupob = iter->dupob->next) {
copy_m4_m4(iter->dupob->ob->obmat, iter->omat);
if (iter->dupli_refob) {
/* Restore last object's real matrix. */
copy_m4_m4(iter->dupli_refob->obmat, iter->omat);
iter->dupli_refob = NULL;
}
free_object_duplilist(iter->duplilist);
iter->duplilist = NULL;
run_again = 1;
run_again = true;
}
}
}