Cycles: Fix shading with autosmooth and custom normals

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!
This commit is contained in:
Sergey Sharybin 2017-02-22 10:53:28 +01:00
parent 2c30fd83f1
commit 36c4fc1ea9
Notes: blender-bot 2023-02-14 08:47:25 +01:00
Referenced by issue #50876, Cycles Crash - Cycles crashes before sampling when certain meshes have autosmooth enabled.
6 changed files with 24 additions and 6 deletions

View 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.

View 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) {

View 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);

View 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. */

View 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;
}

View 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);