Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc
| Show All 26 Lines | |||||
| static void geo_node_mesh_subdivide_declare(NodeDeclarationBuilder &b) | static void geo_node_mesh_subdivide_declare(NodeDeclarationBuilder &b) | ||||
| { | { | ||||
| b.add_input<decl::Geometry>("Geometry"); | b.add_input<decl::Geometry>("Geometry"); | ||||
| b.add_input<decl::Int>("Level").default_value(1).min(0).max(6); | b.add_input<decl::Int>("Level").default_value(1).min(0).max(6); | ||||
| b.add_output<decl::Geometry>("Geometry"); | b.add_output<decl::Geometry>("Geometry"); | ||||
| } | } | ||||
| static void geo_node_mesh_subdivide_exec(GeoNodeExecParams params) | static void geometry_set_mesh_subdivide(GeometrySet &geometry_set, const int level) | ||||
| { | { | ||||
| GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); | |||||
| geometry_set = geometry_set_realize_instances(geometry_set); | |||||
| if (!geometry_set.has_mesh()) { | if (!geometry_set.has_mesh()) { | ||||
| params.set_output("Geometry", geometry_set); | |||||
| return; | |||||
| } | |||||
| #ifndef WITH_OPENSUBDIV | |||||
| params.error_message_add(NodeWarningType::Error, | |||||
| TIP_("Disabled, Blender was compiled without OpenSubdiv")); | |||||
| params.set_output("Geometry", std::move(geometry_set)); | |||||
| return; | |||||
| #endif | |||||
| /* See CCGSUBSURF_LEVEL_MAX for max limit. */ | |||||
| const int subdiv_level = clamp_i(params.extract_input<int>("Level"), 0, 11); | |||||
| if (subdiv_level == 0) { | |||||
| params.set_output("Geometry", std::move(geometry_set)); | |||||
| return; | return; | ||||
| } | } | ||||
| const Mesh *mesh_in = geometry_set.get_mesh_for_read(); | const Mesh *mesh_in = geometry_set.get_mesh_for_read(); | ||||
| /* Initialize mesh settings. */ | /* Initialize mesh settings. */ | ||||
| SubdivToMeshSettings mesh_settings; | SubdivToMeshSettings mesh_settings; | ||||
| mesh_settings.resolution = (1 << subdiv_level) + 1; | mesh_settings.resolution = (1 << level) + 1; | ||||
| mesh_settings.use_optimal_display = false; | mesh_settings.use_optimal_display = false; | ||||
| /* Initialize subdivision settings. */ | /* Initialize subdivision settings. */ | ||||
| SubdivSettings subdiv_settings; | SubdivSettings subdiv_settings; | ||||
| subdiv_settings.is_simple = true; | subdiv_settings.is_simple = true; | ||||
| subdiv_settings.is_adaptive = false; | subdiv_settings.is_adaptive = false; | ||||
| subdiv_settings.use_creases = false; | subdiv_settings.use_creases = false; | ||||
| subdiv_settings.level = 1; | subdiv_settings.level = 1; | ||||
| subdiv_settings.vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf( | subdiv_settings.vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf( | ||||
| 0); | 0); | ||||
| subdiv_settings.fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth(0); | subdiv_settings.fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth(0); | ||||
| /* Apply subdivision from mesh. */ | /* Apply subdivision from mesh. */ | ||||
| Subdiv *subdiv = BKE_subdiv_update_from_mesh(nullptr, &subdiv_settings, mesh_in); | Subdiv *subdiv = BKE_subdiv_update_from_mesh(nullptr, &subdiv_settings, mesh_in); | ||||
| /* In case of bad topology, skip to input mesh. */ | /* In case of bad topology, skip to input mesh. */ | ||||
| if (subdiv == nullptr) { | if (subdiv == nullptr) { | ||||
| params.set_output("Geometry", std::move(geometry_set)); | |||||
| return; | return; | ||||
| } | } | ||||
| Mesh *mesh_out = BKE_subdiv_to_mesh(subdiv, &mesh_settings, mesh_in); | Mesh *mesh_out = BKE_subdiv_to_mesh(subdiv, &mesh_settings, mesh_in); | ||||
| BKE_mesh_normals_tag_dirty(mesh_out); | BKE_mesh_normals_tag_dirty(mesh_out); | ||||
| MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); | MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); | ||||
| mesh_component.replace(mesh_out); | mesh_component.replace(mesh_out); | ||||
| BKE_subdiv_free(subdiv); | BKE_subdiv_free(subdiv); | ||||
| } | |||||
| static void geo_node_mesh_subdivide_exec(GeoNodeExecParams params) | |||||
| { | |||||
| GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); | |||||
| #ifndef WITH_OPENSUBDIV | |||||
| params.error_message_add(NodeWarningType::Error, | |||||
| TIP_("Disabled, Blender was compiled without OpenSubdiv")); | |||||
| params.set_output("Geometry", std::move(geometry_set)); | |||||
| return; | |||||
| #endif | |||||
| /* See CCGSUBSURF_LEVEL_MAX for max limit. */ | |||||
| const int subdiv_level = clamp_i(params.extract_input<int>("Level"), 0, 11); | |||||
| if (subdiv_level == 0) { | |||||
| params.set_output("Geometry", std::move(geometry_set)); | |||||
| return; | |||||
| } | |||||
| geometry_set.modify_geometry_sets( | |||||
| [&](GeometrySet &geometry_set) { geometry_set_mesh_subdivide(geometry_set, subdiv_level); }); | |||||
| params.set_output("Geometry", std::move(geometry_set)); | params.set_output("Geometry", std::move(geometry_set)); | ||||
| } | } | ||||
| } // namespace blender::nodes | } // namespace blender::nodes | ||||
| void register_node_type_geo_mesh_subdivide() | void register_node_type_geo_mesh_subdivide() | ||||
| { | { | ||||
| static bNodeType ntype; | static bNodeType ntype; | ||||
| geo_node_type_base(&ntype, GEO_NODE_MESH_SUBDIVIDE, "Mesh Subdivide", NODE_CLASS_GEOMETRY, 0); | geo_node_type_base(&ntype, GEO_NODE_MESH_SUBDIVIDE, "Mesh Subdivide", NODE_CLASS_GEOMETRY, 0); | ||||
| ntype.declare = blender::nodes::geo_node_mesh_subdivide_declare; | ntype.declare = blender::nodes::geo_node_mesh_subdivide_declare; | ||||
| ntype.geometry_node_execute = blender::nodes::geo_node_mesh_subdivide_exec; | ntype.geometry_node_execute = blender::nodes::geo_node_mesh_subdivide_exec; | ||||
| nodeRegisterType(&ntype); | nodeRegisterType(&ntype); | ||||
| } | } | ||||