diff options
Diffstat (limited to 'editor/import')
-rw-r--r-- | editor/import/resource_importer_scene.cpp | 201 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.h | 202 | ||||
-rw-r--r-- | editor/import/resource_importer_texture.cpp | 2 | ||||
-rw-r--r-- | editor/import/scene_import_settings.cpp | 74 | ||||
-rw-r--r-- | editor/import/scene_import_settings.h | 4 | ||||
-rw-r--r-- | editor/import/scene_importer_mesh.cpp | 80 | ||||
-rw-r--r-- | editor/import/scene_importer_mesh.h | 9 |
7 files changed, 500 insertions, 72 deletions
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index c2244befa1..c48d9bb117 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -49,7 +49,7 @@ #include "scene/resources/separation_ray_shape_3d.h" #include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" -#include "scene/resources/world_margin_shape_3d.h" +#include "scene/resources/world_boundary_shape_3d.h" uint32_t EditorSceneImporter::get_import_flags() const { int ret; @@ -233,13 +233,14 @@ static String _fixstr(const String &p_what, const String &p_str) { return what; } -static void _pre_gen_shape_list(const Ref<EditorSceneImporterMesh> &mesh, List<Ref<Shape3D>> &r_shape_list, bool p_convex) { +static void _pre_gen_shape_list(Ref<EditorSceneImporterMesh> &mesh, Vector<Ref<Shape3D>> &r_shape_list, bool p_convex) { ERR_FAIL_NULL_MSG(mesh, "Cannot generate shape list with null mesh value"); if (!p_convex) { Ref<Shape3D> shape = mesh->create_trimesh_shape(); r_shape_list.push_back(shape); } else { - Vector<Ref<Shape3D>> cd = mesh->convex_decompose(); + Vector<Ref<Shape3D>> cd; + cd.push_back(mesh->get_mesh()->create_convex_shape(true, /*Passing false, otherwise VHACD will be used to simplify (Decompose) the Mesh.*/ false)); if (cd.size()) { for (int i = 0; i < cd.size(); i++) { r_shape_list.push_back(cd[i]); @@ -248,7 +249,7 @@ static void _pre_gen_shape_list(const Ref<EditorSceneImporterMesh> &mesh, List<R } } -Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map) { +Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map) { // children first for (int i = 0; i < p_node->get_child_count(); i++) { Node *r = _pre_fix_node(p_node->get_child(i), p_root, collision_map); @@ -335,7 +336,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { - List<Ref<Shape3D>> shapes; + Vector<Ref<Shape3D>> shapes; String fixed_name; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; @@ -386,8 +387,8 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E colshape->set_shape(rayShape); Object::cast_to<Node3D>(sb)->rotate_x(Math_PI / 2); } else if (empty_draw_type == "IMAGE") { - WorldMarginShape3D *world_margin_shape = memnew(WorldMarginShape3D); - colshape->set_shape(world_margin_shape); + WorldBoundaryShape3D *world_boundary_shape = memnew(WorldBoundaryShape3D); + colshape->set_shape(world_boundary_shape); } else { SphereShape3D *sphereShape = memnew(SphereShape3D); sphereShape->set_radius(1); @@ -406,15 +407,15 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { - List<Ref<Shape3D>> shapes; + Vector<Ref<Shape3D>> shapes; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else { _pre_gen_shape_list(mesh, shapes, true); } - RigidBody3D *rigid_body = memnew(RigidBody3D); - rigid_body->set_name(_fixstr(name, "rigid")); + RigidDynamicBody3D *rigid_body = memnew(RigidDynamicBody3D); + rigid_body->set_name(_fixstr(name, "rigid_body")); p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform()); p_node = rigid_body; @@ -431,7 +432,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { - List<Ref<Shape3D>> shapes; + Vector<Ref<Shape3D>> shapes; String fixed_name; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; @@ -490,7 +491,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); if (!mesh.is_null()) { - List<Ref<Shape3D>> shapes; + Vector<Ref<Shape3D>> shapes; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else if (_teststr(mesh->get_name(), "col")) { @@ -516,7 +517,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E return p_node; } -Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) { +Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) { // children first for (int i = 0; i < p_node->get_child_count(); i++) { Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps); @@ -579,28 +580,35 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } if (node_settings.has("generate/physics")) { - int mesh_physics_mode = node_settings["generate/physics"]; - - if (mesh_physics_mode != MESH_PHYSICS_DISABLED) { - List<Ref<Shape3D>> shapes; + int mesh_physics_mode = MeshPhysicsMode::MESH_PHYSICS_DISABLED; + + const bool generate_collider = node_settings["generate/physics"]; + if (generate_collider) { + mesh_physics_mode = MeshPhysicsMode::MESH_PHYSICS_MESH_AND_STATIC_COLLIDER; + if (node_settings.has("physics/body_type")) { + const BodyType body_type = (BodyType)node_settings["physics/body_type"].operator int(); + switch (body_type) { + case BODY_TYPE_STATIC: + mesh_physics_mode = MeshPhysicsMode::MESH_PHYSICS_MESH_AND_STATIC_COLLIDER; + break; + case BODY_TYPE_DYNAMIC: + mesh_physics_mode = MeshPhysicsMode::MESH_PHYSICS_RIGID_BODY_AND_MESH; + break; + case BODY_TYPE_AREA: + mesh_physics_mode = MeshPhysicsMode::MESH_PHYSICS_AREA_ONLY; + break; + } + } + } + if (mesh_physics_mode != MeshPhysicsMode::MESH_PHYSICS_DISABLED) { + Vector<Ref<Shape3D>> shapes; if (collision_map.has(m)) { shapes = collision_map[m]; } else { - switch (mesh_physics_mode) { - case MESH_PHYSICS_MESH_AND_STATIC_COLLIDER: { - _pre_gen_shape_list(m, shapes, false); - } break; - case MESH_PHYSICS_RIGID_BODY_AND_MESH: { - _pre_gen_shape_list(m, shapes, true); - } break; - case MESH_PHYSICS_STATIC_COLLIDER_ONLY: { - _pre_gen_shape_list(m, shapes, false); - } break; - case MESH_PHYSICS_AREA_ONLY: { - _pre_gen_shape_list(m, shapes, true); - } break; - } + shapes = get_collision_shapes( + m->get_mesh(), + node_settings); } if (shapes.size()) { @@ -609,13 +617,15 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< case MESH_PHYSICS_MESH_AND_STATIC_COLLIDER: { StaticBody3D *col = memnew(StaticBody3D); p_node->add_child(col); + col->set_owner(p_node->get_owner()); + col->set_transform(get_collision_shapes_transform(node_settings)); base = col; } break; case MESH_PHYSICS_RIGID_BODY_AND_MESH: { - RigidBody3D *rigid_body = memnew(RigidBody3D); + RigidDynamicBody3D *rigid_body = memnew(RigidDynamicBody3D); rigid_body->set_name(p_node->get_name()); p_node->replace_by(rigid_body); - rigid_body->set_transform(mi->get_transform()); + rigid_body->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings)); p_node = rigid_body; mi->set_transform(Transform3D()); rigid_body->add_child(mi); @@ -624,7 +634,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } break; case MESH_PHYSICS_STATIC_COLLIDER_ONLY: { StaticBody3D *col = memnew(StaticBody3D); - col->set_transform(mi->get_transform()); + col->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings)); col->set_name(p_node->get_name()); p_node->replace_by(col); memdelete(p_node); @@ -633,7 +643,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } break; case MESH_PHYSICS_AREA_ONLY: { Area3D *area = memnew(Area3D); - area->set_transform(mi->get_transform()); + area->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings)); area->set_name(p_node->get_name()); p_node->replace_by(area); memdelete(p_node); @@ -933,8 +943,35 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p } break; case INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE: { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/physics", PROPERTY_HINT_ENUM, "Disabled,Mesh + Static Collider,Rigid Body + Mesh,Static Collider Only,Area Only"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate/physics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/navmesh", PROPERTY_HINT_ENUM, "Disabled,Mesh + NavMesh,NavMesh Only"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/body_type", PROPERTY_HINT_ENUM, "Static,Dynamic,Area"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/shape_type", PROPERTY_HINT_ENUM, "Decompose Convex,Simple Convex,Trimesh,Box,Sphere,Cylinder,Capsule", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0)); + + // Decomposition + Mesh::ConvexDecompositionSettings decomposition_default; + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/advanced", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/precision", PROPERTY_HINT_RANGE, "1,10,1"), 5)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/max_concavity", PROPERTY_HINT_RANGE, "0.0,1.0,0.001", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.max_concavity)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/symmetry_planes_clipping_bias", PROPERTY_HINT_RANGE, "0.0,1.0,0.001", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.symmetry_planes_clipping_bias)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/revolution_axes_clipping_bias", PROPERTY_HINT_RANGE, "0.0,1.0,0.001", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.revolution_axes_clipping_bias)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/min_volume_per_convex_hull", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.min_volume_per_convex_hull)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/resolution", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.resolution)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/max_num_vertices_per_convex_hull", PROPERTY_HINT_RANGE, "5,512,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.max_num_vertices_per_convex_hull)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/plane_downsampling", PROPERTY_HINT_RANGE, "1,16,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.plane_downsampling)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/convexhull_downsampling", PROPERTY_HINT_RANGE, "1,16,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.convexhull_downsampling)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/normalize_mesh", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.normalize_mesh)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/mode", PROPERTY_HINT_ENUM, "Voxel,Tetrahedron", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), static_cast<int>(decomposition_default.mode))); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/convexhull_approximation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.convexhull_approximation)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/max_convex_hulls", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.max_convex_hulls)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/project_hull_vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.project_hull_vertices)); + + // Primitives: Box, Sphere, Cylinder, Capsule. + r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "primitive/size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), Vector3(2.0, 2.0, 2.0))); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "primitive/height", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1.0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "primitive/radius", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1.0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "primitive/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), Vector3())); + r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "primitive/rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), Vector3())); } break; case INTERNAL_IMPORT_CATEGORY_MESH: { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); @@ -985,6 +1022,65 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor case INTERNAL_IMPORT_CATEGORY_NODE: { } break; case INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE: { + const bool generate_physics = + p_options.has("generate/physics") && + p_options["generate/physics"].operator bool(); + + if ( + p_option == "physics/body_type" || + p_option == "physics/shape_type") { + // Show if need to generate collisions. + return generate_physics; + } + + if (p_option.find("decomposition/") >= 0) { + // Show if need to generate collisions. + if (generate_physics && + // Show if convex is enabled. + p_options["physics/shape_type"] == Variant(SHAPE_TYPE_DECOMPOSE_CONVEX)) { + if (p_option == "decomposition/advanced") { + return true; + } + + const bool decomposition_advanced = + p_options.has("decomposition/advanced") && + p_options["decomposition/advanced"].operator bool(); + + if (p_option == "decomposition/precision") { + return !decomposition_advanced; + } else { + return decomposition_advanced; + } + } + + return false; + } + + if (p_option == "primitive/position" || p_option == "primitive/rotation") { + const ShapeType physics_shape = (ShapeType)p_options["physics/shape_type"].operator int(); + return generate_physics && + physics_shape >= SHAPE_TYPE_BOX; + } + + if (p_option == "primitive/size") { + const ShapeType physics_shape = (ShapeType)p_options["physics/shape_type"].operator int(); + return generate_physics && + physics_shape == SHAPE_TYPE_BOX; + } + + if (p_option == "primitive/radius") { + const ShapeType physics_shape = (ShapeType)p_options["physics/shape_type"].operator int(); + return generate_physics && (physics_shape == SHAPE_TYPE_SPHERE || + physics_shape == SHAPE_TYPE_CYLINDER || + physics_shape == SHAPE_TYPE_CAPSULE); + } + + if (p_option == "primitive/height") { + const ShapeType physics_shape = (ShapeType)p_options["physics/shape_type"].operator int(); + return generate_physics && + (physics_shape == SHAPE_TYPE_CYLINDER || + physics_shape == SHAPE_TYPE_CAPSULE); + } } break; case INTERNAL_IMPORT_CATEGORY_MESH: { if (p_option == "save_to_file/path" || p_option == "save_to_file/make_streamable") { @@ -1021,6 +1117,33 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor return true; } +bool ResourceImporterScene::get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const { + switch (p_category) { + case INTERNAL_IMPORT_CATEGORY_NODE: { + } break; + case INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE: { + if ( + p_option == "generate/physics" || + p_option == "physics/shape_type" || + p_option.find("decomposition/") >= 0 || + p_option.find("primitive/") >= 0) { + return true; + } + } break; + case INTERNAL_IMPORT_CATEGORY_MESH: { + } break; + case INTERNAL_IMPORT_CATEGORY_MATERIAL: { + } break; + case INTERNAL_IMPORT_CATEGORY_ANIMATION: { + } break; + case INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE: { + } break; + default: { + } + } + return false; +} + void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_type", PROPERTY_HINT_TYPE_STRING, "Node"), "Node3D")); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_name"), "Scene Root")); @@ -1275,7 +1398,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m } } -void ResourceImporterScene::_add_shapes(Node *p_node, const List<Ref<Shape3D>> &p_shapes) { +void ResourceImporterScene::_add_shapes(Node *p_node, const Vector<Ref<Shape3D>> &p_shapes) { for (const Ref<Shape3D> &E : p_shapes) { CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E); @@ -1316,7 +1439,7 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file) { return nullptr; } - Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> collision_map; + Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> collision_map; _pre_fix_node(scene, scene, collision_map); @@ -1392,7 +1515,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p } Set<Ref<EditorSceneImporterMesh>> scanned_meshes; - Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> collision_map; + Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> collision_map; _pre_fix_node(scene, scene, collision_map); _post_fix_node(scene, scene, collision_map, scanned_meshes, node_data, material_data, animation_data, fps); diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 542959be02..e232b715be 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -63,7 +63,6 @@ public: IMPORT_FAIL_ON_MISSING_DEPENDENCIES = 4, IMPORT_GENERATE_TANGENT_ARRAYS = 8, IMPORT_USE_NAMED_SKIN_BINDS = 16, - }; virtual uint32_t get_import_flags() const; @@ -125,9 +124,25 @@ class ResourceImporterScene : public ResourceImporter { MESH_OVERRIDE_DISABLE, }; + enum BodyType { + BODY_TYPE_STATIC, + BODY_TYPE_DYNAMIC, + BODY_TYPE_AREA + }; + + enum ShapeType { + SHAPE_TYPE_DECOMPOSE_CONVEX, + SHAPE_TYPE_SIMPLE_CONVEX, + SHAPE_TYPE_TRIMESH, + SHAPE_TYPE_BOX, + SHAPE_TYPE_SPHERE, + SHAPE_TYPE_CYLINDER, + SHAPE_TYPE_CAPSULE, + }; + void _replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner); void _generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<Vector<uint8_t>> &r_lightmap_caches); - void _add_shapes(Node *p_node, const List<Ref<Shape3D>> &p_shapes); + void _add_shapes(Node *p_node, const Vector<Ref<Shape3D>> &p_shapes); public: static ResourceImporterScene *get_singleton() { return singleton; } @@ -159,14 +174,15 @@ public: void get_internal_import_options(InternalImportCategory p_category, List<ImportOption> *r_options) const; bool get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; + bool get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; // Import scenes *after* everything else (such as textures). virtual int get_import_order() const override { return ResourceImporter::IMPORT_ORDER_SCENE; } - Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map); - Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); + Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map); + Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks); void _create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all); @@ -184,6 +200,12 @@ public: virtual bool can_import_threaded() const override { return false; } ResourceImporterScene(); + + template <class M> + static Vector<Ref<Shape3D>> get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options); + + template <class M> + static Transform3D get_collision_shapes_transform(const M &p_options); }; class EditorSceneImporterESCN : public EditorSceneImporter { @@ -196,4 +218,176 @@ public: virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) override; }; +#include "scene/resources/box_shape_3d.h" +#include "scene/resources/capsule_shape_3d.h" +#include "scene/resources/cylinder_shape_3d.h" +#include "scene/resources/sphere_shape_3d.h" + +template <class M> +Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options) { + ShapeType generate_shape_type = SHAPE_TYPE_DECOMPOSE_CONVEX; + if (p_options.has(SNAME("physics/shape_type"))) { + generate_shape_type = (ShapeType)p_options[SNAME("physics/shape_type")].operator int(); + } + + if (generate_shape_type == SHAPE_TYPE_DECOMPOSE_CONVEX) { + Mesh::ConvexDecompositionSettings decomposition_settings; + bool advanced = false; + if (p_options.has(SNAME("decomposition/advanced"))) { + advanced = p_options[SNAME("decomposition/advanced")]; + } + + if (advanced) { + if (p_options.has(SNAME("decomposition/max_concavity"))) { + decomposition_settings.max_concavity = p_options[SNAME("decomposition/max_concavity")]; + } + + if (p_options.has(SNAME("decomposition/symmetry_planes_clipping_bias"))) { + decomposition_settings.symmetry_planes_clipping_bias = p_options[SNAME("decomposition/symmetry_planes_clipping_bias")]; + } + + if (p_options.has(SNAME("decomposition/revolution_axes_clipping_bias"))) { + decomposition_settings.revolution_axes_clipping_bias = p_options[SNAME("decomposition/revolution_axes_clipping_bias")]; + } + + if (p_options.has(SNAME("decomposition/min_volume_per_convex_hull"))) { + decomposition_settings.min_volume_per_convex_hull = p_options[SNAME("decomposition/min_volume_per_convex_hull")]; + } + + if (p_options.has(SNAME("decomposition/resolution"))) { + decomposition_settings.resolution = p_options[SNAME("decomposition/resolution")]; + } + + if (p_options.has(SNAME("decomposition/max_num_vertices_per_convex_hull"))) { + decomposition_settings.max_num_vertices_per_convex_hull = p_options[SNAME("decomposition/max_num_vertices_per_convex_hull")]; + } + + if (p_options.has(SNAME("decomposition/plane_downsampling"))) { + decomposition_settings.plane_downsampling = p_options[SNAME("decomposition/plane_downsampling")]; + } + + if (p_options.has(SNAME("decomposition/convexhull_downsampling"))) { + decomposition_settings.convexhull_downsampling = p_options[SNAME("decomposition/convexhull_downsampling")]; + } + + if (p_options.has(SNAME("decomposition/normalize_mesh"))) { + decomposition_settings.normalize_mesh = p_options[SNAME("decomposition/normalize_mesh")]; + } + + if (p_options.has(SNAME("decomposition/mode"))) { + decomposition_settings.mode = (Mesh::ConvexDecompositionSettings::Mode)p_options[SNAME("decomposition/mode")].operator int(); + } + + if (p_options.has(SNAME("decomposition/convexhull_approximation"))) { + decomposition_settings.convexhull_approximation = p_options[SNAME("decomposition/convexhull_approximation")]; + } + + if (p_options.has(SNAME("decomposition/max_convex_hulls"))) { + decomposition_settings.max_convex_hulls = p_options[SNAME("decomposition/max_convex_hulls")]; + } + + if (p_options.has(SNAME("decomposition/project_hull_vertices"))) { + decomposition_settings.project_hull_vertices = p_options[SNAME("decomposition/project_hull_vertices")]; + } + } else { + int precision_level = 5; + if (p_options.has(SNAME("decomposition/precision"))) { + precision_level = p_options[SNAME("decomposition/precision")]; + } + + const real_t precision = real_t(precision_level - 1) / 9.0; + + decomposition_settings.max_concavity = Math::lerp(real_t(1.0), real_t(0.001), precision); + decomposition_settings.min_volume_per_convex_hull = Math::lerp(real_t(0.01), real_t(0.0001), precision); + decomposition_settings.resolution = Math::lerp(10'000, 100'000, precision); + decomposition_settings.max_num_vertices_per_convex_hull = Math::lerp(32, 64, precision); + decomposition_settings.plane_downsampling = Math::lerp(3, 16, precision); + decomposition_settings.convexhull_downsampling = Math::lerp(3, 16, precision); + decomposition_settings.max_convex_hulls = Math::lerp(1, 32, precision); + } + + return p_mesh->convex_decompose(decomposition_settings); + } else if (generate_shape_type == SHAPE_TYPE_SIMPLE_CONVEX) { + Vector<Ref<Shape3D>> shapes; + shapes.push_back(p_mesh->create_convex_shape(true, /*Passing false, otherwise VHACD will be used to simplify (Decompose) the Mesh.*/ false)); + return shapes; + } else if (generate_shape_type == SHAPE_TYPE_TRIMESH) { + Vector<Ref<Shape3D>> shapes; + shapes.push_back(p_mesh->create_trimesh_shape()); + return shapes; + } else if (generate_shape_type == SHAPE_TYPE_BOX) { + Ref<BoxShape3D> box; + box.instantiate(); + if (p_options.has(SNAME("primitive/size"))) { + box->set_size(p_options[SNAME("primitive/size")]); + } + + Vector<Ref<Shape3D>> shapes; + shapes.push_back(box); + return shapes; + + } else if (generate_shape_type == SHAPE_TYPE_SPHERE) { + Ref<SphereShape3D> sphere; + sphere.instantiate(); + if (p_options.has(SNAME("primitive/radius"))) { + sphere->set_radius(p_options[SNAME("primitive/radius")]); + } + + Vector<Ref<Shape3D>> shapes; + shapes.push_back(sphere); + return shapes; + } else if (generate_shape_type == SHAPE_TYPE_CYLINDER) { + Ref<CylinderShape3D> cylinder; + cylinder.instantiate(); + if (p_options.has(SNAME("primitive/height"))) { + cylinder->set_height(p_options[SNAME("primitive/height")]); + } + if (p_options.has(SNAME("primitive/radius"))) { + cylinder->set_radius(p_options[SNAME("primitive/radius")]); + } + + Vector<Ref<Shape3D>> shapes; + shapes.push_back(cylinder); + return shapes; + } else if (generate_shape_type == SHAPE_TYPE_CAPSULE) { + Ref<CapsuleShape3D> capsule; + capsule.instantiate(); + if (p_options.has(SNAME("primitive/height"))) { + capsule->set_height(p_options[SNAME("primitive/height")]); + } + if (p_options.has(SNAME("primitive/radius"))) { + capsule->set_radius(p_options[SNAME("primitive/radius")]); + } + + Vector<Ref<Shape3D>> shapes; + shapes.push_back(capsule); + return shapes; + } + return Vector<Ref<Shape3D>>(); +} + +template <class M> +Transform3D ResourceImporterScene::get_collision_shapes_transform(const M &p_options) { + Transform3D transform; + + ShapeType generate_shape_type = SHAPE_TYPE_DECOMPOSE_CONVEX; + if (p_options.has(SNAME("physics/shape_type"))) { + generate_shape_type = (ShapeType)p_options[SNAME("physics/shape_type")].operator int(); + } + + if (generate_shape_type == SHAPE_TYPE_BOX || + generate_shape_type == SHAPE_TYPE_SPHERE || + generate_shape_type == SHAPE_TYPE_CYLINDER || + generate_shape_type == SHAPE_TYPE_CAPSULE) { + if (p_options.has(SNAME("primitive/position"))) { + transform.origin = p_options[SNAME("primitive/position")]; + } + + if (p_options.has(SNAME("primitive/rotation"))) { + transform.basis.set_euler((p_options[SNAME("primitive/rotation")].operator Vector3() / 180.0) * Math_PI); + } + } + return transform; +} + #endif // RESOURCEIMPORTERSCENE_H diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index daf7b15794..61745cb6ee 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -393,7 +393,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String float lossy = p_options["compress/lossy_quality"]; int pack_channels = p_options["compress/channel_pack"]; bool mipmaps = p_options["mipmaps/generate"]; - uint32_t mipmap_limit = int(mipmaps ? int(p_options["mipmaps/limit"]) : int(-1)); + uint32_t mipmap_limit = mipmaps ? uint32_t(p_options["mipmaps/limit"]) : uint32_t(-1); bool fix_alpha_border = p_options["process/fix_alpha_border"]; bool premult_alpha = p_options["process/premult_alpha"]; bool normal_map_invert_y = p_options["process/normal_map_invert_y"]; diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 19a8f209bb..4bcb6863fb 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -53,6 +53,11 @@ class SceneImportSettingsData : public Object { } current[p_name] = p_value; + + if (ResourceImporterScene::get_singleton()->get_internal_option_update_view_required(category, p_name, current)) { + SceneImportSettings::get_singleton()->update_view(); + } + return true; } return false; @@ -317,6 +322,13 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) { if (mesh_node && mesh_node->get_mesh().is_valid()) { _fill_mesh(scene_tree, mesh_node->get_mesh(), item); + // Add the collider view. + MeshInstance3D *collider_view = memnew(MeshInstance3D); + collider_view->set_name("collider_view"); + collider_view->set_visible(false); + mesh_node->add_child(collider_view); + collider_view->set_owner(mesh_node); + Transform3D accum_xform; Node3D *base = mesh_node; while (base) { @@ -346,6 +358,54 @@ void SceneImportSettings::_update_scene() { _fill_scene(scene, nullptr); } +void SceneImportSettings::_update_view_gizmos() { + for (const KeyValue<String, NodeData> &e : node_map) { + bool generate_collider = false; + if (e.value.settings.has(SNAME("generate/physics"))) { + generate_collider = e.value.settings[SNAME("generate/physics")]; + } + + MeshInstance3D *mesh_node = Object::cast_to<MeshInstance3D>(e.value.node); + if (mesh_node == nullptr || mesh_node->get_mesh().is_null()) { + // Nothing to do + continue; + } + + MeshInstance3D *collider_view = static_cast<MeshInstance3D *>(mesh_node->find_node("collider_view")); + CRASH_COND_MSG(collider_view == nullptr, "This is unreachable, since the collider view is always created even when the collision is not used! If this is triggered there is a bug on the function `_fill_scene`."); + + collider_view->set_visible(generate_collider); + if (generate_collider) { + // This collider_view doesn't have a mesh so we need to generate a new one. + + // Generate the mesh collider. + Vector<Ref<Shape3D>> shapes = ResourceImporterScene::get_collision_shapes(mesh_node->get_mesh(), e.value.settings); + const Transform3D transform = ResourceImporterScene::get_collision_shapes_transform(e.value.settings); + + Ref<ArrayMesh> collider_view_mesh; + collider_view_mesh.instantiate(); + for (Ref<Shape3D> shape : shapes) { + Ref<ArrayMesh> debug_shape_mesh; + if (shape.is_valid()) { + debug_shape_mesh = shape->get_debug_mesh(); + } + if (debug_shape_mesh.is_valid()) { + collider_view_mesh->add_surface_from_arrays( + debug_shape_mesh->surface_get_primitive_type(0), + debug_shape_mesh->surface_get_arrays(0)); + + collider_view_mesh->surface_set_material( + collider_view_mesh->get_surface_count() - 1, + collider_mat); + } + } + + collider_view->set_mesh(collider_view_mesh); + collider_view->set_transform(transform); + } + } +} + void SceneImportSettings::_update_camera() { AABB camera_aabb; @@ -404,11 +464,16 @@ void SceneImportSettings::_load_default_subresource_settings(Map<StringName, Var } } +void SceneImportSettings::update_view() { + _update_view_gizmos(); +} + void SceneImportSettings::open_settings(const String &p_path) { if (scene) { memdelete(scene); scene = nullptr; } + scene_import_settings_data->settings = nullptr; scene = ResourceImporterScene::get_singleton()->pre_import(p_path); if (scene == nullptr) { EditorNode::get_singleton()->show_warning(TTR("Error opening scene")); @@ -463,6 +528,7 @@ void SceneImportSettings::open_settings(const String &p_path) { } popup_centered_ratio(); + _update_view_gizmos(); _update_camera(); set_title(vformat(TTR("Advanced Import Settings for '%s'"), base_path.get_file())); @@ -629,6 +695,7 @@ void SceneImportSettings::_material_tree_selected() { _select(material_tree, type, import_id); } + void SceneImportSettings::_mesh_tree_selected() { if (selecting) { return; @@ -640,6 +707,7 @@ void SceneImportSettings::_mesh_tree_selected() { _select(mesh_tree, type, import_id); } + void SceneImportSettings::_scene_tree_selected() { if (selecting) { return; @@ -1144,6 +1212,12 @@ SceneImportSettings::SceneImportSettings() { material_preview.instantiate(); } + { + collider_mat.instantiate(); + collider_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + collider_mat->set_albedo(Color(0.5, 0.5, 1.0)); + } + inspector = memnew(EditorInspector); inspector->set_custom_minimum_size(Size2(300 * EDSCALE, 0)); diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h index ddcf4a6d5d..c7c94af493 100644 --- a/editor/import/scene_import_settings.h +++ b/editor/import/scene_import_settings.h @@ -84,6 +84,8 @@ class SceneImportSettings : public ConfirmationDialog { MeshInstance3D *mesh_preview; Ref<SphereMesh> material_preview; + Ref<StandardMaterial3D> collider_mat; + float cam_rot_x; float cam_rot_y; float cam_zoom; @@ -145,6 +147,7 @@ class SceneImportSettings : public ConfirmationDialog { bool selecting = false; + void _update_view_gizmos(); void _update_camera(); void _select(Tree *p_from, String p_type, String p_id); void _material_tree_selected(); @@ -190,6 +193,7 @@ protected: void _notification(int p_what); public: + void update_view(); void open_settings(const String &p_path); static SceneImportSettings *get_singleton(); SceneImportSettings(); diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp index 06f373c54f..5e6dd08e79 100644 --- a/editor/import/scene_importer_mesh.cpp +++ b/editor/import/scene_importer_mesh.cpp @@ -33,6 +33,8 @@ #include "core/math/math_defs.h" #include "scene/resources/surface_tool.h" +#include <cstdint> + void EditorSceneImporterMesh::add_blend_shape(const String &p_name) { ERR_FAIL_COND(surfaces.size() > 0); blend_shapes.push_back(p_name); @@ -55,13 +57,14 @@ Mesh::BlendShapeMode EditorSceneImporterMesh::get_blend_shape_mode() const { return blend_shape_mode; } -void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name) { +void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name, const uint32_t p_flags) { ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size()); ERR_FAIL_COND(p_arrays.size() != Mesh::ARRAY_MAX); Surface s; s.primitive = p_primitive; s.arrays = p_arrays; s.name = p_name; + s.flags = p_flags; Vector<Vector3> vertex_array = p_arrays[Mesh::ARRAY_VERTEX]; int vertex_count = vertex_array.size(); @@ -138,6 +141,11 @@ float EditorSceneImporterMesh::get_surface_lod_size(int p_surface, int p_lod) co return surfaces[p_surface].lods[p_lod].distance; } +uint32_t EditorSceneImporterMesh::get_surface_format(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0); + return surfaces[p_surface].flags; +} + Ref<Material> EditorSceneImporterMesh::get_surface_material(int p_surface) const { ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Ref<Material>()); return surfaces[p_surface].material; @@ -283,7 +291,7 @@ Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh(const Ref<ArrayMesh> &p_base) { } } - mesh->add_surface_from_arrays(surfaces[i].primitive, surfaces[i].arrays, bs_data, lods); + mesh->add_surface_from_arrays(surfaces[i].primitive, surfaces[i].arrays, bs_data, lods, surfaces[i].flags); if (surfaces[i].material.is_valid()) { mesh->surface_set_material(mesh->get_surface_count() - 1, surfaces[i].material); } @@ -398,7 +406,7 @@ void EditorSceneImporterMesh::create_shadow_mesh() { } } - shadow_mesh->add_surface(surfaces[i].primitive, new_surface, Array(), lods, Ref<Material>(), surfaces[i].name); + shadow_mesh->add_surface(surfaces[i].primitive, new_surface, Array(), lods, Ref<Material>(), surfaces[i].name, surfaces[i].flags); } } @@ -436,7 +444,11 @@ void EditorSceneImporterMesh::_set_data(const Dictionary &p_data) { if (s.has("material")) { material = s["material"]; } - add_surface(prim, arr, blend_shapes, lods, material, name); + uint32_t flags = 0; + if (s.has("flags")) { + flags = s["flags"]; + } + add_surface(prim, arr, blend_shapes, lods, material, name, flags); } } } @@ -473,6 +485,10 @@ Dictionary EditorSceneImporterMesh::_get_data() const { d["name"] = surfaces[i].name; } + if (surfaces[i].flags != 0) { + d["flags"] = surfaces[i].flags; + } + surface_arr.push_back(d); } data["surfaces"] = surface_arr; @@ -508,36 +524,47 @@ Vector<Face3> EditorSceneImporterMesh::get_faces() const { return faces; } -Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose() const { - ERR_FAIL_COND_V(!Mesh::convex_composition_function, Vector<Ref<Shape3D>>()); +Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const { + ERR_FAIL_COND_V(!Mesh::convex_decomposition_function, Vector<Ref<Shape3D>>()); const Vector<Face3> faces = get_faces(); + int face_count = faces.size(); + + Vector<Vector3> vertices; + uint32_t vertex_count = 0; + vertices.resize(face_count * 3); + Vector<uint32_t> indices; + indices.resize(face_count * 3); + { + Map<Vector3, uint32_t> vertex_map; + Vector3 *vertex_w = vertices.ptrw(); + uint32_t *index_w = indices.ptrw(); + for (int i = 0; i < face_count; i++) { + for (int j = 0; j < 3; j++) { + const Vector3 &vertex = faces[i].vertex[j]; + Map<Vector3, uint32_t>::Element *found_vertex = vertex_map.find(vertex); + uint32_t index; + if (found_vertex) { + index = found_vertex->get(); + } else { + index = ++vertex_count; + vertex_map[vertex] = index; + vertex_w[index] = vertex; + } + index_w[i * 3 + j] = index; + } + } + } + vertices.resize(vertex_count); - Vector<Vector<Face3>> decomposed = Mesh::convex_composition_function(faces, -1); + Vector<Vector<Vector3>> decomposed = Mesh::convex_decomposition_function((real_t *)vertices.ptr(), vertex_count, indices.ptr(), face_count, p_settings, nullptr); Vector<Ref<Shape3D>> ret; for (int i = 0; i < decomposed.size(); i++) { - Set<Vector3> points; - for (int j = 0; j < decomposed[i].size(); j++) { - points.insert(decomposed[i][j].vertex[0]); - points.insert(decomposed[i][j].vertex[1]); - points.insert(decomposed[i][j].vertex[2]); - } - - Vector<Vector3> convex_points; - convex_points.resize(points.size()); - { - Vector3 *w = convex_points.ptrw(); - int idx = 0; - for (Set<Vector3>::Element *E = points.front(); E; E = E->next()) { - w[idx++] = E->get(); - } - } - Ref<ConvexPolygonShape3D> shape; shape.instantiate(); - shape->set_points(convex_points); + shape->set_points(decomposed[i]); ret.push_back(shape); } @@ -833,7 +860,7 @@ void EditorSceneImporterMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &EditorSceneImporterMesh::set_blend_shape_mode); ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &EditorSceneImporterMesh::get_blend_shape_mode); - ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material", "name"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String())); + ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material", "name", "flags"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String()), DEFVAL(0)); ClassDB::bind_method(D_METHOD("get_surface_count"), &EditorSceneImporterMesh::get_surface_count); ClassDB::bind_method(D_METHOD("get_surface_primitive_type", "surface_idx"), &EditorSceneImporterMesh::get_surface_primitive_type); @@ -844,6 +871,7 @@ void EditorSceneImporterMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_surface_lod_size", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_size); ClassDB::bind_method(D_METHOD("get_surface_lod_indices", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_indices); ClassDB::bind_method(D_METHOD("get_surface_material", "surface_idx"), &EditorSceneImporterMesh::get_surface_material); + ClassDB::bind_method(D_METHOD("get_surface_format", "surface_idx"), &EditorSceneImporterMesh::get_surface_format); ClassDB::bind_method(D_METHOD("set_surface_name", "surface_idx", "name"), &EditorSceneImporterMesh::set_surface_name); ClassDB::bind_method(D_METHOD("set_surface_material", "surface_idx", "material"), &EditorSceneImporterMesh::set_surface_material); diff --git a/editor/import/scene_importer_mesh.h b/editor/import/scene_importer_mesh.h index e57e479d8e..d32b1fdf74 100644 --- a/editor/import/scene_importer_mesh.h +++ b/editor/import/scene_importer_mesh.h @@ -36,6 +36,9 @@ #include "scene/resources/convex_polygon_shape_3d.h" #include "scene/resources/mesh.h" #include "scene/resources/navigation_mesh.h" + +#include <cstdint> + // The following classes are used by importers instead of ArrayMesh and MeshInstance3D // so the data is not registered (hence, quality loss), importing happens faster and // its easier to modify before saving @@ -57,6 +60,7 @@ class EditorSceneImporterMesh : public Resource { Vector<LOD> lods; Ref<Material> material; String name; + uint32_t flags = 0; }; Vector<Surface> surfaces; Vector<String> blend_shapes; @@ -80,7 +84,7 @@ public: int get_blend_shape_count() const; String get_blend_shape_name(int p_blend_shape) const; - void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref<Material> &p_material = Ref<Material>(), const String &p_name = String()); + void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref<Material> &p_material = Ref<Material>(), const String &p_name = String(), const uint32_t p_flags = 0); int get_surface_count() const; void set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode); @@ -95,6 +99,7 @@ public: Vector<int> get_surface_lod_indices(int p_surface, int p_lod) const; float get_surface_lod_size(int p_surface, int p_lod) const; Ref<Material> get_surface_material(int p_surface) const; + uint32_t get_surface_format(int p_surface) const; void set_surface_material(int p_surface, const Ref<Material> &p_material); @@ -104,7 +109,7 @@ public: Ref<EditorSceneImporterMesh> get_shadow_mesh() const; Vector<Face3> get_faces() const; - Vector<Ref<Shape3D>> convex_decompose() const; + Vector<Ref<Shape3D>> convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const; Ref<Shape3D> create_trimesh_shape() const; Ref<NavigationMesh> create_navigation_mesh(); Error lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache); |