Fix T47038: Particles in Particle Edit Mode get added in completely wrong location.
[blender.git] / source / blender / render / intern / source / convertblender.c
index 1da1a81fe95c1c7a6271ba5e01a134d657ba387d..69e45fea74dbfd22f361a464a55a393c7debcdf9 100644 (file)
@@ -44,7 +44,7 @@
 #  include "BLI_edgehash.h"
 #endif
 
-#include "BLF_translation.h"
+#include "BLT_translation.h"
 
 #include "DNA_material_types.h"
 #include "DNA_curve_types.h"
 
 /* ------------------------------------------------------------------------- */
 
+#define CD_MASK_RENDER_INTERNAL \
+    (CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL)
+
 static void split_v_renderfaces(ObjectRen *obr, int startvlak, int UNUSED(startvert), int UNUSED(usize), int vsize, int uIndex, int UNUSED(cyclu), int cyclv)
 {
        int vLen = vsize-1+(!!cyclv);
@@ -137,29 +140,30 @@ static void split_v_renderfaces(ObjectRen *obr, int startvlak, int UNUSED(startv
 
        for (v=0; v<vLen; v++) {
                VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v);
+               VlakRen *vlr_other;
                VertRen *vert = RE_vertren_copy(obr, vlr->v2);
 
                if (cyclv) {
                        vlr->v2 = vert;
 
-                       if (v==vLen-1) {
-                               VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + 0);
-                               vlr->v1 = vert;
+                       if (v == vLen - 1) {
+                               vlr_other = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + 0);
+                               vlr_other->v1 = vert;
                        }
                        else {
-                               VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1);
-                               vlr->v1 = vert;
+                               vlr_other = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1);
+                               vlr_other->v1 = vert;
                        }
                }
                else {
                        vlr->v2 = vert;
 
-                       if (v<vLen-1) {
-                               VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1);
-                               vlr->v1 = vert;
+                       if (v < vLen - 1) {
+                               vlr_other = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1);
+                               vlr_other->v1 = vert;
                        }
 
-                       if (v==0) {
+                       if (v == 0) {
                                vlr->v1 = RE_vertren_copy(obr, vlr->v1);
                        }
                }
@@ -378,7 +382,7 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, bool do_verte
 {
        int a;
 
-               /* clear all vertex normals */
+       /* clear all vertex normals */
        if (do_vertex_normal) {
                for (a=0; a<obr->totvert; a++) {
                        VertRen *ver= RE_findOrAddVert(obr, a);
@@ -386,8 +390,8 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, bool do_verte
                }
        }
 
-               /* calculate cos of angles and point-masses, use as weight factor to
-                * add face normal to vertex */
+       /* calculate cos of angles and point-masses, use as weight factor to
+        * add face normal to vertex */
        for (a=0; a<obr->totvlak; a++) {
                VlakRen *vlr= RE_findOrAddVlak(obr, a);
                if (do_vertex_normal && vlr->flag & ME_SMOOTH) {
@@ -404,7 +408,7 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, bool do_verte
                }
        }
 
-               /* do solid faces */
+       /* do solid faces */
        for (a=0; a<obr->totvlak; a++) {
                VlakRen *vlr= RE_findOrAddVlak(obr, a);
 
@@ -1250,7 +1254,7 @@ static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int
        /* get uvco */
        if (sd->uvco && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
                for (i=0; i<sd->totuv; i++) {
-                       if (num != DMCACHE_NOTFOUND) {
+                       if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
                                MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
                                MTFace *mtface = (MTFace*)CustomData_get_layer_n(&dm->faceData, CD_MTFACE, i);
                                mtface += num;
@@ -1388,16 +1392,16 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
 
        re->flag |= R_HALO;
 
-       RE_set_customdata_names(obr, &psmd->dm->faceData);
-       sd.totuv = CustomData_number_of_layers(&psmd->dm->faceData, CD_MTFACE);
-       sd.totcol = CustomData_number_of_layers(&psmd->dm->faceData, CD_MCOL);
+       RE_set_customdata_names(obr, &psmd->dm_final->faceData);
+       sd.totuv = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MTFACE);
+       sd.totcol = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MCOL);
 
        if (ma->texco & TEXCO_UV && sd.totuv) {
                sd.uvco = MEM_callocN(sd.totuv * 2 * sizeof(float), "particle_uvs");
 
                if (ma->strand_uvname[0]) {
-                       sd.override_uv = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, ma->strand_uvname);
-                       sd.override_uv -= CustomData_get_layer_index(&psmd->dm->faceData, CD_MTFACE);
+                       sd.override_uv = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, ma->strand_uvname);
+                       sd.override_uv -= CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
                }
        }
        else
@@ -1408,15 +1412,15 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
 
 /* 2.2 setup billboards */
        if (part->ren_as == PART_DRAW_BB) {
-               int first_uv = CustomData_get_layer_index(&psmd->dm->faceData, CD_MTFACE);
+               int first_uv = CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
 
-               bb.uv[0] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[0]);
+               bb.uv[0] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[0]);
                if (bb.uv[0] < 0)
-                       bb.uv[0] = CustomData_get_active_layer_index(&psmd->dm->faceData, CD_MTFACE);
+                       bb.uv[0] = CustomData_get_active_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
 
-               bb.uv[1] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[1]);
+               bb.uv[1] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[1]);
 
-               bb.uv[2] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[2]);
+               bb.uv[2] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[2]);
 
                if (first_uv >= 0) {
                        bb.uv[0] -= first_uv;
@@ -1496,9 +1500,9 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                if (ma->amb != 0.0f)
                                        do_surfacecache = true;
 
-                       totface= psmd->dm->getNumTessFaces(psmd->dm);
-                       index_mf_to_mpoly = psmd->dm->getTessFaceDataArray(psmd->dm, CD_ORIGINDEX);
-                       index_mp_to_orig = psmd->dm->getPolyDataArray(psmd->dm, CD_ORIGINDEX);
+                       totface= psmd->dm_final->getNumTessFaces(psmd->dm_final);
+                       index_mf_to_mpoly = psmd->dm_final->getTessFaceDataArray(psmd->dm_final, CD_ORIGINDEX);
+                       index_mp_to_orig = psmd->dm_final->getPolyDataArray(psmd->dm_final, CD_ORIGINDEX);
                        if (index_mf_to_mpoly == NULL) {
                                index_mp_to_orig = NULL;
                        }
@@ -1553,10 +1557,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                        num= pa->num_dmcache;
 
                        if (num == DMCACHE_NOTFOUND)
-                               if (pa->num < psmd->dm->getNumTessFaces(psmd->dm))
+                               if (pa->num < psmd->dm_final->getNumTessFaces(psmd->dm_final))
                                        num= pa->num;
 
-                       get_particle_uvco_mcol(part->from, psmd->dm, pa->fuv, num, &sd);
+                       get_particle_uvco_mcol(part->from, psmd->dm_final, pa->fuv, num, &sd);
 
                        pa_size = pa->size;
 
@@ -1607,17 +1611,17 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
 
                        /* get uvco & mcol */
                        if (part->childtype==PART_CHILD_FACES) {
-                               get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm, cpa->fuv, cpa->num, &sd);
+                               get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm_final, cpa->fuv, cpa->num, &sd);
                        }
                        else {
                                ParticleData *parent = psys->particles + cpa->parent;
                                num = parent->num_dmcache;
 
                                if (num == DMCACHE_NOTFOUND)
-                                       if (parent->num < psmd->dm->getNumTessFaces(psmd->dm))
+                                       if (parent->num < psmd->dm_final->getNumTessFaces(psmd->dm_final))
                                                num = parent->num;
 
-                               get_particle_uvco_mcol(part->from, psmd->dm, parent->fuv, num, &sd);
+                               get_particle_uvco_mcol(part->from, psmd->dm_final, parent->fuv, num, &sd);
                        }
 
                        do_simplify = psys_render_simplify_params(psys, cpa, simplify);
@@ -1733,14 +1737,14 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                                sub_v3_v3v3(loc0, loc1, loc);
                                                add_v3_v3v3(loc0, loc1, loc0);
 
-                                               particle_curve(re, obr, psmd->dm, ma, &sd, loc1, loc0, seed, pa_co);
+                                               particle_curve(re, obr, psmd->dm_final, ma, &sd, loc1, loc0, seed, pa_co);
                                        }
 
                                        sd.first = 0;
                                        sd.time = time;
 
                                        if (k)
-                                               particle_curve(re, obr, psmd->dm, ma, &sd, loc, loc1, seed, pa_co);
+                                               particle_curve(re, obr, psmd->dm_final, ma, &sd, loc, loc1, seed, pa_co);
 
                                        copy_v3_v3(loc1, loc);
                                }
@@ -1799,7 +1803,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                        pa_co[0] = (part->draw & PART_ABS_PATH_TIME) ? (ct-pa_birthtime)/(pa_dietime-pa_birthtime) : ct;
                                        pa_co[1] = (float)i/(float)(trail_count-1);
 
-                                       particle_normal_ren(part->ren_as, part, re, obr, psmd->dm, ma, &sd, &bb, &state, seed, hasize, pa_co);
+                                       particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co);
                                }
                        }
                        else {
@@ -1835,7 +1839,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                        bb.lifetime = pa_dietime-pa_birthtime;
                                }
 
-                               particle_normal_ren(part->ren_as, part, re, obr, psmd->dm, ma, &sd, &bb, &state, seed, hasize, pa_co);
+                               particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co);
                        }
                }
 
@@ -1847,7 +1851,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
        }
 
        if (do_surfacecache)
-               strandbuf->surface= cache_strand_surface(re, obr, psmd->dm, mat, timeoffset);
+               strandbuf->surface= cache_strand_surface(re, obr, psmd->dm_final, mat, timeoffset);
 
 /* 4. clean up */
 #if 0  /* XXX old animation system */
@@ -3175,7 +3179,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
        /* origindex currently used when using autosmooth, or baking to vertex colors. */
        need_origindex = (do_autosmooth || ((re->flag & R_BAKING) && (re->r.bake_flag & R_BAKE_VCOL)));
 
-       mask= CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL;
+       mask = CD_MASK_RENDER_INTERNAL;
        if (!timeoffset)
                if (need_orco)
                        mask |= CD_MASK_ORCO;
@@ -3269,8 +3273,14 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
                        RE_set_customdata_names(obr, &dm->faceData);
 
                        /* add tangent layer if we need one */
-                       if (need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1)
-                               DM_add_tangent_layer(dm);
+                       if (need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) {
+                               bool generate_data = false;
+                               if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) {
+                                       dm->calcLoopTangents(dm);
+                                       generate_data = true;
+                               }
+                               DM_generate_tangent_tessface_data(dm, generate_data);
+                       }
                        
                        /* still to do for keys: the correct local texture coordinate */
 
@@ -3946,7 +3956,7 @@ static void add_lightgroup(Render *re, Group *group, int exclusive)
 {
        GroupObject *go, *gol;
        
-       group->id.flag &= ~LIB_DOIT;
+       group->id.tag &= ~LIB_TAG_DOIT;
 
        /* it's a bit too many loops in loops... but will survive */
        /* note that 'exclusive' will remove it from the global list */
@@ -3985,12 +3995,12 @@ static void set_material_lightgroups(Render *re)
                return;
        
        for (group= re->main->group.first; group; group=group->id.next)
-               group->id.flag |= LIB_DOIT;
+               group->id.tag |= LIB_TAG_DOIT;
        
        /* it's a bit too many loops in loops... but will survive */
        /* hola! materials not in use...? */
        for (ma= re->main->mat.first; ma; ma=ma->id.next) {
-               if (ma->group && (ma->group->id.flag & LIB_DOIT))
+               if (ma->group && (ma->group->id.tag & LIB_TAG_DOIT))
                        add_lightgroup(re, ma->group, ma->mode & MA_GROUP_NOLAY);
        }
 }
@@ -4581,10 +4591,12 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset)
                        /* the emitter mesh wasn't rendered so the modifier stack wasn't
                         * evaluated with render settings */
                        DerivedMesh *dm;
+                       const CustomDataMask mask = CD_MASK_RENDER_INTERNAL;
+
                        if (re->r.scemode & R_VIEWPORT_PREVIEW)
-                               dm = mesh_create_derived_view(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+                               dm = mesh_create_derived_view(re->scene, ob, mask);
                        else
-                               dm = mesh_create_derived_render(re->scene, ob,  CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+                               dm = mesh_create_derived_render(re->scene, ob, mask);
                        dm->release(dm);
                }
 
@@ -4647,7 +4659,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
 
                /* only add instance for objects that have not been used for dupli */
                if (!(ob->transflag & OB_RENDER_DUPLI)) {
-                       obi= RE_addRenderInstance(re, obr, ob, par, index, 0, NULL, ob->lay);
+                       obi = RE_addRenderInstance(re, obr, ob, par, index, 0, NULL, ob->lay, dob);
                        if (dob) set_dupli_tex_mat(re, obi, dob, omat);
                }
                else
@@ -4676,12 +4688,12 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
                                psys->flag |= PSYS_USE_IMAT;
                        init_render_object_data(re, obr, timeoffset);
                        if (!(re->r.scemode & R_VIEWPORT_PREVIEW))
-                               psys_render_restore(ob, psys);
+                               psys_render_restore(re->scene, ob, psys);
                        psys->flag &= ~PSYS_USE_IMAT;
 
                        /* only add instance for objects that have not been used for dupli */
                        if (!(ob->transflag & OB_RENDER_DUPLI)) {
-                               obi= RE_addRenderInstance(re, obr, ob, par, index, psysindex, NULL, ob->lay);
+                               obi = RE_addRenderInstance(re, obr, ob, par, index, psysindex, NULL, ob->lay, dob);
                                if (dob) set_dupli_tex_mat(re, obi, dob, omat);
                        }
                        else
@@ -4876,7 +4888,7 @@ static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, in
                                if (enable)
                                        psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset);
                                else
-                                       psys_render_restore(ob, psys);
+                                       psys_render_restore(re->scene, ob, psys);
                        }
                }
 
@@ -4884,7 +4896,7 @@ static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, in
                        /* this is to make sure we get render level duplis in groups:
                         * the derivedmesh must be created before init_render_mesh,
                         * since object_duplilist does dupliparticles before that */
-                       dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+                       dm = mesh_create_derived_render(re->scene, ob, CD_MASK_RENDER_INTERNAL);
                        dm->release(dm);
 
                        for (psys=ob->particlesystem.first; psys; psys=psys->next)
@@ -5005,7 +5017,9 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
                                dupli_render_particle_set(re, ob, timeoffset, 0, 1);
                                duplilist = object_duplilist(re->eval_ctx, re->scene, ob);
                                duplilist_apply_data = duplilist_apply(ob, NULL, duplilist);
-                               dupli_render_particle_set(re, ob, timeoffset, 0, 0);
+                               /* postpone 'dupli_render_particle_set', since RE_addRenderInstance reads
+                                * index values from 'dob->persistent_id[0]', referencing 'psys->child' which
+                                * may be smaller once the particle system is restored, see: T45563. */
 
                                for (dob= duplilist->first, i = 0; dob; dob= dob->next, ++i) {
                                        DupliExtraData *dob_extra = &duplilist_apply_data->extra[i];
@@ -5040,7 +5054,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
                                                if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, 0))) {
                                                        mul_m4_m4m4(mat, re->viewmat, dob->mat);
                                                                                                                /* ob = particle system, use that layer */
-                                                       obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], 0, mat, ob->lay); 
+                                                       obi = RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], 0, mat, ob->lay, dob);
 
                                                        /* fill in instance variables for texturing */
                                                        set_dupli_tex_mat(re, obi, dob, dob_extra->obmat);
@@ -5067,7 +5081,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
                                                        if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, psysindex))) {
                                                                if (obi == NULL)
                                                                        mul_m4_m4m4(mat, re->viewmat, dob->mat);
-                                                               obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], psysindex++, mat, obd->lay);
+                                                               obi = RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], psysindex++, mat, obd->lay, dob);
 
                                                                set_dupli_tex_mat(re, obi, dob, dob_extra->obmat);
                                                                if (dob->type != OB_DUPLIGROUP) {
@@ -5098,6 +5112,9 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
                                        if (re->test_break(re->tbh)) break;
                                }
 
+                               /* restore particle system */
+                               dupli_render_particle_set(re, ob, timeoffset, 0, false);
+
                                if (duplilist_apply_data) {
                                        duplilist_restore(duplilist, duplilist_apply_data);
                                        duplilist_free_apply_data(duplilist_apply_data);
@@ -5194,7 +5211,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
        /* still bad... doing all */
        init_render_textures(re);
        copy_v3_v3(amb, &re->wrld.ambr);
-       init_render_materials(re->main, re->r.mode, amb);
+       init_render_materials(re->main, re->r.mode, amb, (re->r.scemode & R_BUTS_PREVIEW) == 0);
        set_node_shader_lamp_loop(shade_material_loop);
 
        /* MAKE RENDER DATA */
@@ -5925,7 +5942,7 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
        init_render_textures(re);
        
        copy_v3_v3(amb, &re->wrld.ambr);
-       init_render_materials(re->main, re->r.mode, amb);
+       init_render_materials(re->main, re->r.mode, amb, true);
        
        set_node_shader_lamp_loop(shade_material_loop);