Fix T60615: Cycles baking not working with some modifiers.

Refactors Cycles mesh export a bit to avoid unnecessary copies and to be in
sync with the Blender baker.
This commit is contained in:
2019-01-15 13:03:09 +01:00
parent 985dcbf6db
commit c9938ebb00
5 changed files with 72 additions and 95 deletions

View File

@@ -756,13 +756,11 @@ static void create_mesh(Scene *scene,
return; return;
} }
BL::Mesh::vertices_iterator v;
BL::Mesh::polygons_iterator p;
if(!subdivision) { if(!subdivision) {
numtris = numfaces; numtris = numfaces;
} }
else { else {
BL::Mesh::polygons_iterator p;
for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
numngons += (p->loop_total() == 4)? 0: 1; numngons += (p->loop_total() == 4)? 0: 1;
numcorners += p->loop_total(); numcorners += p->loop_total();
@@ -774,6 +772,7 @@ static void create_mesh(Scene *scene,
mesh->reserve_subd_faces(numfaces, numngons, numcorners); mesh->reserve_subd_faces(numfaces, numngons, numcorners);
/* create vertex coordinates and normals */ /* create vertex coordinates and normals */
BL::Mesh::vertices_iterator v;
for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
mesh->add_vertex(get_float3(v->co())); mesh->add_vertex(get_float3(v->co()));
@@ -808,13 +807,10 @@ static void create_mesh(Scene *scene,
} }
/* create faces */ /* create faces */
vector<int> nverts(numfaces);
if(!subdivision) { if(!subdivision) {
BL::Mesh::loop_triangles_iterator t; BL::Mesh::loop_triangles_iterator t;
int ti = 0;
for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t, ++ti) { for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
BL::MeshPolygon p = b_mesh.polygons[t->polygon_index()]; BL::MeshPolygon p = b_mesh.polygons[t->polygon_index()];
int3 vi = get_int3(t->vertices()); int3 vi = get_int3(t->vertices());
@@ -835,10 +831,10 @@ static void create_mesh(Scene *scene,
* NOTE: Autosmooth is already taken care about. * NOTE: Autosmooth is already taken care about.
*/ */
mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth); mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
nverts[ti] = 3;
} }
} }
else { else {
BL::Mesh::polygons_iterator p;
vector<int> vi; vector<int> vi;
for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
@@ -1065,37 +1061,26 @@ Mesh *BlenderSync::sync_mesh(BL::Depsgraph& b_depsgraph,
mesh->name = ustring(b_ob_data.name().c_str()); mesh->name = ustring(b_ob_data.name().c_str());
if(requested_geometry_flags != Mesh::GEOMETRY_NONE) { if(requested_geometry_flags != Mesh::GEOMETRY_NONE) {
/* mesh objects does have special handle in the dependency graph, /* Adaptive subdivision setup. Not for baking since that requires
* they're ensured to have properly updated. * exact mapping to the Blender mesh. */
*
* updating meshes here will end up having derived mesh referencing
* freed data from the blender side.
*/
if(preview && b_ob.type() != BL::Object::type_MESH) {
b_ob.update_from_editmode(b_data);
}
/* For some reason, meshes do not need this... */
bool apply_modifiers = (b_ob.type() != BL::Object::type_MESH);
bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental);
/* Disable adaptive subdivision while baking as the baking system
* currently doesnt support the topology and will crash.
*/
if(scene->bake_manager->get_baking()) { if(scene->bake_manager->get_baking()) {
mesh->subdivision_type = Mesh::SUBDIVISION_NONE; mesh->subdivision_type = Mesh::SUBDIVISION_NONE;
} }
else {
mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental);
}
/* For some reason, meshes do not need this... */
bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
BL::Mesh b_mesh = object_to_mesh(b_data, BL::Mesh b_mesh = object_to_mesh(b_data,
b_ob, b_ob,
b_depsgraph, b_depsgraph,
apply_modifiers,
need_undeformed, need_undeformed,
mesh->subdivision_type); mesh->subdivision_type);
if(b_mesh) { if(b_mesh) {
/* Sync mesh itself. */
if(view_layer.use_surfaces && show_self) { if(view_layer.use_surfaces && show_self) {
if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE) if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE)
create_subd_mesh(scene, mesh, b_ob, b_mesh, used_shaders, create_subd_mesh(scene, mesh, b_ob, b_mesh, used_shaders,
@@ -1106,11 +1091,12 @@ Mesh *BlenderSync::sync_mesh(BL::Depsgraph& b_depsgraph,
create_mesh_volume_attributes(scene, b_ob, mesh, b_scene.frame_current()); create_mesh_volume_attributes(scene, b_ob, mesh, b_scene.frame_current());
} }
if(view_layer.use_hair && show_particles && mesh->subdivision_type == Mesh::SUBDIVISION_NONE) /* Sync hair curves. */
if(view_layer.use_hair && show_particles && mesh->subdivision_type == Mesh::SUBDIVISION_NONE) {
sync_curves(mesh, b_mesh, b_ob, false); sync_curves(mesh, b_mesh, b_ob, false);
}
/* free derived mesh */ free_object_to_mesh(b_data, b_ob, b_mesh);
b_data.meshes.remove(b_mesh, false, true, false);
} }
} }
mesh->geometry_flags = requested_geometry_flags; mesh->geometry_flags = requested_geometry_flags;
@@ -1176,7 +1162,6 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph& b_depsgraph,
b_ob, b_ob,
b_depsgraph, b_depsgraph,
false, false,
false,
Mesh::SUBDIVISION_NONE); Mesh::SUBDIVISION_NONE);
} }
@@ -1287,7 +1272,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph& b_depsgraph,
sync_curves(mesh, b_mesh, b_ob, true, motion_step); sync_curves(mesh, b_mesh, b_ob, true, motion_step);
/* free derived mesh */ /* free derived mesh */
b_data.meshes.remove(b_mesh, false, true, false); free_object_to_mesh(b_data, b_ob, b_mesh);
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -47,14 +47,14 @@ void python_thread_state_restore(void **python_thread_state);
static inline BL::Mesh object_to_mesh(BL::BlendData& data, static inline BL::Mesh object_to_mesh(BL::BlendData& data,
BL::Object& object, BL::Object& object,
BL::Depsgraph& depsgraph, BL::Depsgraph& depsgraph,
bool apply_modifiers,
bool calc_undeformed, bool calc_undeformed,
Mesh::SubdivisionType subdivision_type) Mesh::SubdivisionType subdivision_type)
{ {
/* TODO: make this work with copy-on-write, modifiers are already evaluated. */
#if 0
bool subsurf_mod_show_render = false; bool subsurf_mod_show_render = false;
bool subsurf_mod_show_viewport = false; bool subsurf_mod_show_viewport = false;
/* TODO: make this work with copy-on-write, modifiers are already evaluated. */
if(subdivision_type != Mesh::SUBDIVISION_NONE) { if(subdivision_type != Mesh::SUBDIVISION_NONE) {
BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1]; BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
@@ -64,31 +64,51 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
subsurf_mod.show_render(false); subsurf_mod.show_render(false);
subsurf_mod.show_viewport(false); subsurf_mod.show_viewport(false);
} }
#endif
BL::Mesh me = data.meshes.new_from_object(depsgraph, object, apply_modifiers, calc_undeformed); BL::Mesh mesh(PointerRNA_NULL);
if(object.type() == BL::Object::type_MESH) {
/* TODO: calc_undeformed is not used. */
mesh = BL::Mesh(object.data());
/* Make a copy to split faces if we use autosmooth, otherwise not needed. */
if (mesh.use_auto_smooth() && subdivision_type == Mesh::SUBDIVISION_NONE) {
mesh = data.meshes.new_from_object(depsgraph, object, false, false);
}
}
else {
mesh = data.meshes.new_from_object(depsgraph, object, true, calc_undeformed);
}
#if 0
if(subdivision_type != Mesh::SUBDIVISION_NONE) { if(subdivision_type != Mesh::SUBDIVISION_NONE) {
BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1]; BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
subsurf_mod.show_render(subsurf_mod_show_render); subsurf_mod.show_render(subsurf_mod_show_render);
subsurf_mod.show_viewport(subsurf_mod_show_viewport); subsurf_mod.show_viewport(subsurf_mod_show_viewport);
} }
#endif
if((bool)me) { if((bool)mesh && subdivision_type == Mesh::SUBDIVISION_NONE) {
if(me.use_auto_smooth()) { if(mesh.use_auto_smooth()) {
if(subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK) { mesh.split_faces(false);
me.calc_normals_split();
} }
else {
me.split_faces(false); mesh.calc_loop_triangles();
} }
return mesh;
} }
if(subdivision_type == Mesh::SUBDIVISION_NONE) {
me.calc_loop_triangles(); static inline void free_object_to_mesh(BL::BlendData& data,
BL::Object& object,
BL::Mesh& mesh)
{
/* Free mesh if we didn't just use the existing one. */
if(object.data().ptr.data != mesh.ptr.data) {
data.meshes.remove(mesh, false, true, false);
} }
} }
return me;
}
static inline void colorramp_to_array(BL::ColorRamp& ramp, static inline void colorramp_to_array(BL::ColorRamp& ramp,
array<float3>& ramp_color, array<float3>& ramp_color,

View File

@@ -580,30 +580,6 @@ void Mesh::clear(bool preserve_voxel_data)
patch_table = NULL; patch_table = NULL;
} }
int Mesh::split_vertex(int vertex)
{
/* copy vertex location and vertex attributes */
add_vertex_slow(verts[vertex]);
foreach(Attribute& attr, attributes.attributes) {
if(attr.element == ATTR_ELEMENT_VERTEX) {
array<char> tmp(attr.data_sizeof());
memcpy(tmp.data(), attr.data() + tmp.size()*vertex, tmp.size());
attr.add(tmp.data());
}
}
foreach(Attribute& attr, subd_attributes.attributes) {
if(attr.element == ATTR_ELEMENT_VERTEX) {
array<char> tmp(attr.data_sizeof());
memcpy(tmp.data(), attr.data() + tmp.size()*vertex, tmp.size());
attr.add(tmp.data());
}
}
return verts.size() - 1;
}
void Mesh::add_vertex(float3 P) void Mesh::add_vertex(float3 P)
{ {
verts.push_back_reserved(P); verts.push_back_reserved(P);

View File

@@ -274,7 +274,6 @@ public:
void add_curve_key(float3 loc, float radius); void add_curve_key(float3 loc, float radius);
void add_curve(int first_key, int shader); void add_curve(int first_key, int shader);
void add_subd_face(int* corners, int num_corners, int shader_, bool smooth_); void add_subd_face(int* corners, int num_corners, int shader_, bool smooth_);
int split_vertex(int vertex);
void compute_bounds(); void compute_bounds();
void add_face_normals(); void add_face_normals();

View File

@@ -635,15 +635,9 @@ static size_t initialize_internal_images(BakeImages *bake_images, ReportList *re
/* create new mesh with edit mode changes and modifiers applied */ /* create new mesh with edit mode changes and modifiers applied */
static Mesh *bake_mesh_new_from_object(Depsgraph *depsgraph, Main *bmain, Scene *scene, Object *ob) static Mesh *bake_mesh_new_from_object(Depsgraph *depsgraph, Main *bmain, Scene *scene, Object *ob)
{ {
bool apply_modifiers = false; bool apply_modifiers = (ob->type != OB_MESH);
Mesh *me = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob, apply_modifiers, false);
/* Mesh is already updated and has modifiers applied. */
if (ob->type != OB_MESH) {
ED_object_editmode_load(bmain, ob);
apply_modifiers = true;
}
Mesh *me = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob, apply_modifiers, 0);
if (me->flag & ME_AUTOSMOOTH) { if (me->flag & ME_AUTOSMOOTH) {
BKE_mesh_split_faces(me, true); BKE_mesh_split_faces(me, true);
} }
@@ -812,7 +806,7 @@ static int bake(
ob_low_eval = DEG_get_evaluated_object(depsgraph, ob_low); ob_low_eval = DEG_get_evaluated_object(depsgraph, ob_low);
/* get the mesh as it arrives in the renderer */ /* get the mesh as it arrives in the renderer */
me_low = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low); me_low = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval);
/* populate the pixel array with the face data */ /* populate the pixel array with the face data */
if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false) if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
@@ -825,7 +819,7 @@ static int bake(
/* prepare cage mesh */ /* prepare cage mesh */
if (ob_cage) { if (ob_cage) {
me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_cage); me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_cage_eval);
if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) { if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
BKE_report(reports, RPT_ERROR, BKE_report(reports, RPT_ERROR,
"Invalid cage object, the cage mesh must have the same number " "Invalid cage object, the cage mesh must have the same number "
@@ -834,6 +828,8 @@ static int bake(
} }
} }
else if (is_cage) { else if (is_cage) {
BKE_object_eval_reset(ob_low_eval);
ModifierData *md = ob_low_eval->modifiers.first; ModifierData *md = ob_low_eval->modifiers.first;
while (md) { while (md) {
ModifierData *md_next = md->next; ModifierData *md_next = md->next;
@@ -851,7 +847,6 @@ static int bake(
md = md_next; md = md_next;
} }
BKE_object_eval_reset(ob_low_eval);
me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval); me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval);
RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer); RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
} }
@@ -867,10 +862,10 @@ static int bake(
/* initialize highpoly_data */ /* initialize highpoly_data */
highpoly[i].ob = ob_iter; highpoly[i].ob = ob_iter;
highpoly[i].me = bake_mesh_new_from_object(depsgraph, bmain, scene, highpoly[i].ob);
highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter); highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER; highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER;
highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER); highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER);
highpoly[i].me = bake_mesh_new_from_object(depsgraph, bmain, scene, highpoly[i].ob_eval);
/* lowpoly to highpoly transformation matrix */ /* lowpoly to highpoly transformation matrix */
copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat); copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
@@ -894,7 +889,7 @@ static int bake(
/* populate the pixel arrays with the corresponding face data for each high poly object */ /* populate the pixel arrays with the corresponding face data for each high poly object */
if (!RE_bake_pixels_populate_from_objects( if (!RE_bake_pixels_populate_from_objects(
me_low, pixel_array_low, pixel_array_high, highpoly, tot_highpoly, num_pixels, ob_cage != NULL, me_low, pixel_array_low, pixel_array_high, highpoly, tot_highpoly, num_pixels, ob_cage != NULL,
cage_extrusion, ob_low->obmat, (ob_cage ? ob_cage->obmat : ob_low->obmat), me_cage)) cage_extrusion, ob_low_eval->obmat, (ob_cage ? ob_cage->obmat : ob_low_eval->obmat), me_cage))
{ {
BKE_report(reports, RPT_ERROR, "Error handling selected objects"); BKE_report(reports, RPT_ERROR, "Error handling selected objects");
goto cleanup; goto cleanup;
@@ -912,10 +907,10 @@ static int bake(
} }
else { else {
/* If low poly is not renderable it should have failed long ago. */ /* If low poly is not renderable it should have failed long ago. */
BLI_assert((ob_low->restrictflag & OB_RESTRICT_RENDER) == 0); BLI_assert((ob_low_eval->restrictflag & OB_RESTRICT_RENDER) == 0);
if (RE_bake_has_engine(re)) { if (RE_bake_has_engine(re)) {
ok = RE_bake_engine(re, depsgraph, ob_low, 0, pixel_array_low, num_pixels, depth, pass_type, pass_filter, result); ok = RE_bake_engine(re, depsgraph, ob_low_eval, 0, pixel_array_low, num_pixels, depth, pass_type, pass_filter, result);
} }
else { else {
BKE_report(reports, RPT_ERROR, "Current render engine does not support baking"); BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
@@ -943,13 +938,13 @@ static int bake(
} }
case R_BAKE_SPACE_OBJECT: case R_BAKE_SPACE_OBJECT:
{ {
RE_bake_normal_world_to_object(pixel_array_low, num_pixels, depth, result, ob_low, normal_swizzle); RE_bake_normal_world_to_object(pixel_array_low, num_pixels, depth, result, ob_low_eval, normal_swizzle);
break; break;
} }
case R_BAKE_SPACE_TANGENT: case R_BAKE_SPACE_TANGENT:
{ {
if (is_selected_to_active) { if (is_selected_to_active) {
RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_low, normal_swizzle, ob_low->obmat); RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_low, normal_swizzle, ob_low_eval->obmat);
} }
else { else {
/* from multiresolution */ /* from multiresolution */
@@ -957,17 +952,19 @@ static int bake(
ModifierData *md = NULL; ModifierData *md = NULL;
int mode; int mode;
md = modifiers_findByType(ob_low, eModifierType_Multires); BKE_object_eval_reset(ob_low_eval);
md = modifiers_findByType(ob_low_eval, eModifierType_Multires);
if (md) { if (md) {
mode = md->mode; mode = md->mode;
md->mode &= ~eModifierMode_Render; md->mode &= ~eModifierMode_Render;
} }
me_nores = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low); /* Evaluate modifiers again. */
me_nores = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval, true, false);
RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer); RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat); RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low_eval->obmat);
BKE_id_free(bmain, me_nores); BKE_id_free(bmain, me_nores);
if (md) if (md)
@@ -1029,8 +1026,8 @@ static int bake(
BLI_path_suffix(name, FILE_MAX, bk_image->image->id.name + 2, "_"); BLI_path_suffix(name, FILE_MAX, bk_image->image->id.name + 2, "_");
} }
else { else {
if (ob_low->mat[i]) { if (ob_low_eval->mat[i]) {
BLI_path_suffix(name, FILE_MAX, ob_low->mat[i]->id.name + 2, "_"); BLI_path_suffix(name, FILE_MAX, ob_low_eval->mat[i]->id.name + 2, "_");
} }
else if (me_low->mat[i]) { else if (me_low->mat[i]) {
BLI_path_suffix(name, FILE_MAX, me_low->mat[i]->id.name + 2, "_"); BLI_path_suffix(name, FILE_MAX, me_low->mat[i]->id.name + 2, "_");