Cycles: Fix shading with autosmooth and custom normals
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 22 Feb 2017 09:53:28 +0000 (10:53 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 22 Feb 2017 09:54:36 +0000 (10:54 +0100)
New logic of split_faces was leaving mesh in a proper state
from Blender's point of view, but Cycles wanted loop normals
to be "flushed" to vertex normals.

Now we do such a flush from Cycles side again, so we don't
leave bad meshes behind.

Thanks Bastien for assistance here!

intern/cycles/blender/blender_mesh.cpp
intern/cycles/blender/blender_util.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/mesh.c
source/blender/editors/object/object_bake_api.c
source/blender/makesrna/intern/rna_mesh_api.c

index a1ff81e750a9edf5a9484d6bdc08efe680efad9d..fdc287084eb116c81b059b0e5048d4395bb80298 100644 (file)
@@ -777,6 +777,15 @@ static void create_mesh(Scene *scene,
                        int shader = clamp(f->material_index(), 0, used_shaders.size()-1);
                        bool smooth = f->use_smooth() || use_loop_normals;
 
+                       if(use_loop_normals) {
+                               BL::Array<float, 12> loop_normals = f->split_normals();
+                               for(int i = 0; i < n; i++) {
+                                       N[vi[i]] = make_float3(loop_normals[i * 3],
+                                                              loop_normals[i * 3 + 1],
+                                                              loop_normals[i * 3 + 2]);
+                               }
+                       }
+
                        /* Create triangles.
                         *
                         * NOTE: Autosmooth is already taken care about.
index 8120de9636246b2bbc8b296413d512f74edd9cbd..23df3c1bc304c92465f356cf78ccb9fec9ec272e 100644 (file)
@@ -79,7 +79,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
                                me.calc_normals_split();
                        }
                        else {
-                               me.split_faces();
+                               me.split_faces(false);
                        }
                }
                if(subdivision_type == Mesh::SUBDIVISION_NONE) {
index e42692622f4db5c61b84c5858d14adeecc9a4c3c..b83bec5a30206903449a7b23b548869de4b4fc94 100644 (file)
@@ -131,7 +131,7 @@ bool BKE_mesh_uv_cdlayer_rename(struct Mesh *me, const char *old_name, const cha
 
 float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3];
 
-void BKE_mesh_split_faces(struct Mesh *mesh);
+void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
 
 struct Mesh *BKE_mesh_new_from_object(struct Main *bmain, struct Scene *sce, struct Object *ob,
                                       int apply_modifiers, int settings, int calc_tessface, int calc_undeformed);
index 7a27c43e28fa1af50468ba22058cf2f413d7cc40..918032b2df8cf99b3ba43012184151b5112d13ff 100644 (file)
@@ -2338,7 +2338,7 @@ static void split_faces_split_new_edges(
  * NOTE: Will leave CD_NORMAL loop data layer which is
  * used by render engines to set shading up.
  */
-void BKE_mesh_split_faces(Mesh *mesh)
+void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
 {
        const int num_polys = mesh->totpoly;
 
@@ -2392,7 +2392,9 @@ void BKE_mesh_split_faces(Mesh *mesh)
        /* Note: after this point mesh is expected to be valid again. */
 
        /* CD_NORMAL is expected to be temporary only. */
-       CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop);
+       if (free_loop_normals) {
+               CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop);
+       }
 
        if (lnors_spacearr) {
                /* Also frees new_verts/edges temp data, since we used its memarena to allocate them. */
index fd95d6129adcc247914297010199f9ef0cd80ea2..6b06e7b0a6ca2becc82eef5ec3b8c034dcdb21a5 100644 (file)
@@ -619,7 +619,7 @@ static Mesh *bake_mesh_new_from_object(Main *bmain, Scene *scene, Object *ob)
                ED_object_editmode_load(ob);
 
        Mesh *me = BKE_mesh_new_from_object(bmain, scene, ob, 1, 2, 0, 0);
-       BKE_mesh_split_faces(me);
+       BKE_mesh_split_faces(me, true);
 
        return me;
 }
index ff9873fb3d1601dc5542ad58fe4b015ede57922a..9b0a25560f99f24a94ad6e4a1c78409883045809 100644 (file)
@@ -209,6 +209,11 @@ static void rna_Mesh_flip_normals(Mesh *mesh)
        DAG_id_tag_update(&mesh->id, 0);
 }
 
+static void rna_Mesh_split_faces(Mesh *mesh, int free_loop_normals)
+{
+       BKE_mesh_split_faces(mesh, free_loop_normals != 0);
+}
+
 #else
 
 void RNA_api_mesh(StructRNA *srna)
@@ -240,8 +245,10 @@ void RNA_api_mesh(StructRNA *srna)
        func = RNA_def_function(srna, "free_normals_split", "rna_Mesh_free_normals_split");
        RNA_def_function_ui_description(func, "Free split vertex normals");
 
-       func = RNA_def_function(srna, "split_faces", "BKE_mesh_split_faces");
+       func = RNA_def_function(srna, "split_faces", "rna_Mesh_split_faces");
        RNA_def_function_ui_description(func, "Split faces based on the edge angle");
+       RNA_def_boolean(func, "free_loop_normals", 1, "Free Loop Notmals",
+                       "Free loop normals custom data layer");
 
        func = RNA_def_function(srna, "calc_tangents", "rna_Mesh_calc_tangents");
        RNA_def_function_flag(func, FUNC_USE_REPORTS);