Bug fix: Render and 3d view conflict over ob->imat
authorJanne Karhu <jhkarh@gmail.com>
Mon, 28 Feb 2011 15:42:15 +0000 (15:42 +0000)
committerJanne Karhu <jhkarh@gmail.com>
Mon, 28 Feb 2011 15:42:15 +0000 (15:42 +0000)
* For rendering every object's inverse matrix "ob->imat" needs to
  be in render view coordinates, but for drawing in 3d view it needs
  to be in global coordinates. Originally (way back in historical
  times) ob->imat was only used for rendering, but over the years
  other uses came up too. Before 2.5 this wasn't a problem as
  rendering was a totally blocking operation, but with the new
  "interactive ui while rendering" the problems started. Basically
  any update that redrew the 3d view while rendering (like rotating
  the scene with mouse) updated the inverse matrix into global
  coordinates thus invalidating it for the render, leading to all
  kinds of strange discontinuities with textures and volumetrics.

* Problems were very easy to achieve using orco/object coordinates
  for pretty much any textures (bump, point density, volume, sky),
  for examples see bug reports 24906 and 25229. Render baking normals
  in object coordinates was wrong most of the time too.

* Now there is a separate inverse matrix ob->imat_ren that's
  calculated at the beginning of rendering and is used in all places
  inside render code where it's needed. This way the original ob->imat
  can change at will during rendering without causing problems.

source/blender/makesdna/DNA_object_types.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/render_texture.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/renderdatabase.c

index 8c0e065e27feb0b3cb661e05f1ea989da0a7ad87..c97a1d8fef5addbae5f8c01ae6cc61310b2c53a2 100644 (file)
@@ -145,7 +145,13 @@ typedef struct Object {
        float obmat[4][4];              /* final worldspace matrix with constraints & animsys applied */
        float parentinv[4][4]; /* inverse result of parent, so that object doesn't 'stick' to parent */
        float constinv[4][4]; /* inverse result of constraints. doesn't include effect of parent or object local transform */
-       float imat[4][4];       /* inverse matrix of 'obmat' for during render, old game engine, temporally: ipokeys of transform  */
+       float imat[4][4];       /* inverse matrix of 'obmat' for any other use than rendering! */
+       
+       /* Previously 'imat' was used at render time, but as other places use it too
+        * the interactive ui of 2.5 creates problems. So now only 'imat_ren' should
+        * be used when ever the inverse of ob->obmat * re->viewmat is needed! - jahka
+        */
+       float imat_ren[4][4];
        
        unsigned int lay;                               /* copy of Base */
        
index 5ecb62130f765138430bda9cd449d1c0d7fc21cf..fbc23cbb457a0e2aa56bcced82cd4689ea11a3ed 100644 (file)
@@ -4810,7 +4810,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
        ObjectInstanceRen *obi;
        Scene *sce_iter;
        float mat[4][4];
-       int lay, vectorlay, redoimat= 0;
+       int lay, vectorlay;
 
        /* for duplis we need the Object texture mapping to work as if
         * untransformed, set_dupli_tex_mat sets the matrix to allow that
@@ -4821,7 +4821,8 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
                ob= base->object;
                /* imat objects has to be done here, since displace can have texture using Object map-input */
                mul_m4_m4m4(mat, ob->obmat, re->viewmat);
-               invert_m4_m4(ob->imat, mat);
+               invert_m4_m4(ob->imat_ren, mat);
+               copy_m4_m4(ob->imat, ob->imat_ren);
                /* each object should only be rendered once */
                ob->flag &= ~OB_DONE;
                ob->transflag &= ~OB_RENDER_DUPLI;
@@ -4855,8 +4856,6 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
                                DupliObject *dob;
                                ListBase *lb;
 
-                               redoimat= 1;
-
                                /* create list of duplis generated by this object, particle
                                 * system need to have render settings set for dupli particles */
                                dupli_render_particle_set(re, ob, timeoffset, 0, 1);
@@ -4968,15 +4967,6 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
        for(group= re->main->group.first; group; group=group->id.next)
                add_group_render_dupli_obs(re, group, nolamps, onlyselected, actob, timeoffset, renderlay, 0);
 
-       /* imat objects has to be done again, since groups can mess it up */
-       if(redoimat) {
-               for(SETLOOPER(re->scene, sce_iter, base)) {
-                       ob= base->object;
-                       mul_m4_m4m4(mat, ob->obmat, re->viewmat);
-                       invert_m4_m4(ob->imat, mat);
-               }
-       }
-
        if(!re->test_break(re->tbh))
                RE_makeRenderInstances(re);
 }
index 497fa6b0fcd542353c494f4988ebc0de440a7cf6..acc69680487eaa5a68f5b842591d1832bcb54578 100644 (file)
@@ -1830,8 +1830,8 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
                idv = (dv < 1e-5f) ? bf : (bf/dv);
 
                if ((mtex->texco == TEXCO_ORCO) && shi->obr && shi->obr->ob) {
-                       mul_mat3_m4_v3(shi->obr->ob->imat, tu);
-                       mul_mat3_m4_v3(shi->obr->ob->imat, tv);
+                       mul_mat3_m4_v3(shi->obr->ob->imat_ren, tu);
+                       mul_mat3_m4_v3(shi->obr->ob->imat_ren, tv);
                        normalize_v3(tu);
                        normalize_v3(tv);
                }
@@ -1840,8 +1840,8 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
                        mul_mat3_m4_v3(R.viewinv, tv);
                }
                else if (mtex->texco == TEXCO_OBJECT && mtex->object) {
-                       mul_mat3_m4_v3(mtex->object->imat, tu);
-                       mul_mat3_m4_v3(mtex->object->imat, tv);
+                       mul_mat3_m4_v3(mtex->object->imat_ren, tu);
+                       mul_mat3_m4_v3(mtex->object->imat_ren, tv);
                        normalize_v3(tu);
                        normalize_v3(tv);
                }
@@ -2177,12 +2177,12 @@ void do_material_tex(ShadeInput *shi)
                                        if(mtex->texflag & MTEX_OB_DUPLI_ORIG)
                                                if(shi->obi && shi->obi->duplitexmat)
                                                        mul_m4_v3(shi->obi->duplitexmat, tempvec);
-                                       mul_m4_v3(ob->imat, tempvec);
+                                       mul_m4_v3(ob->imat_ren, tempvec);
                                        if(shi->osatex) {
                                                VECCOPY(dxt, shi->dxco);
                                                VECCOPY(dyt, shi->dyco);
-                                               mul_mat3_m4_v3(ob->imat, dxt);
-                                               mul_mat3_m4_v3(ob->imat, dyt);
+                                               mul_mat3_m4_v3(ob->imat_ren, dxt);
+                                               mul_mat3_m4_v3(ob->imat_ren, dyt);
                                        }
                                }
                                else {
@@ -2653,7 +2653,7 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa
                                                if(shi->obi && shi->obi->duplitexmat)
                                                        mul_m4_v3(shi->obi->duplitexmat, co);                                   
                                        } 
-                                       mul_m4_v3(ob->imat, co);
+                                       mul_m4_v3(ob->imat_ren, co);
                                }
                        }
                        /* not really orco, but 'local' */
@@ -2665,7 +2665,7 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa
                                else {
                                        Object *ob= shi->obi->ob;
                                        VECCOPY(co, xyz);
-                                       mul_m4_v3(ob->imat, co);
+                                       mul_m4_v3(ob->imat_ren, co);
                                }
                        }
                        else if(mtex->texco==TEXCO_GLOB) {                                                      
@@ -3016,7 +3016,7 @@ void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, f
                        case TEXCO_OBJECT:
                                if(mtex->object) {
                                        VECCOPY(tempvec, lo);
-                                       mul_m4_v3(mtex->object->imat, tempvec);
+                                       mul_m4_v3(mtex->object->imat_ren, tempvec);
                                        co= tempvec;
                                }
                                break;
@@ -3165,12 +3165,12 @@ void do_lamp_tex(LampRen *la, float *lavec, ShadeInput *shi, float *colf, int ef
                                        dx= dxt;
                                        dy= dyt;
                                        VECCOPY(tempvec, shi->co);
-                                       mul_m4_v3(ob->imat, tempvec);
+                                       mul_m4_v3(ob->imat_ren, tempvec);
                                        if(shi->osatex) {
                                                VECCOPY(dxt, shi->dxco);
                                                VECCOPY(dyt, shi->dyco);
-                                               mul_mat3_m4_v3(ob->imat, dxt);
-                                               mul_mat3_m4_v3(ob->imat, dyt);
+                                               mul_mat3_m4_v3(ob->imat_ren, dxt);
+                                               mul_mat3_m4_v3(ob->imat_ren, dyt);
                                        }
                                }
                                else {
index bd904c2337fe6357d27e2b5d8992472f5c95ac73..b30e4241c069ee0912aa71cc202bc41365b58dfe 100644 (file)
@@ -2179,7 +2179,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int
                                mul_m3_v3(imat, nor);
                        }
                        else if(R.r.bake_normal_space == R_BAKE_SPACE_OBJECT)
-                               mul_mat3_m4_v3(ob->imat, nor); /* ob->imat includes viewinv! */
+                               mul_mat3_m4_v3(ob->imat_ren, nor); /* ob->imat_ren includes viewinv! */
                        else if(R.r.bake_normal_space == R_BAKE_SPACE_WORLD)
                                mul_mat3_m4_v3(R.viewinv, nor);
 
index 99fe20a729b87c924b17f82b1d8520fc0af12961..74c99d1a92f6414c2e49fbd295b3ab16d9032789 100644 (file)
@@ -1129,16 +1129,8 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater
                                ;
                        }
                        else if(mtex->texco & TEXCO_OBJECT) {
-                               if(mtex->object){
-                                       float imat[4][4];
-                                       /* imat should really be cached somewhere before this */
-                                       invert_m4_m4(imat,mtex->object->obmat);
-                                       mul_m4_v3(imat,texvec);
-                               }
-                               /* texvec[0]+= imatbase->ivec[0]; */
-                               /* texvec[1]+= imatbase->ivec[1]; */
-                               /* texvec[2]+= imatbase->ivec[2]; */
-                               /* mul_m3_v3(imatbase->imat, texvec); */
+                               if(mtex->object)
+                                       mul_m4_v3(mtex->object->imat_ren,texvec);
                        }
                        else if(mtex->texco & TEXCO_GLOB){
                                VECCOPY(texvec,vec);