From 5bf810b5db953d3f58acdd2d05d5410897f41d63 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 7 Jun 2017 18:18:55 -0300 Subject: -Added proper access to depth texture from shader -Split Mesh into Mesh (abstrat class) and ArrayMesh, to allow to proper mesh primitives, as well as streamable meshes in the future. --- drivers/gles3/shader_compiler_gles3.cpp | 1 + editor/import/editor_import_collada.cpp | 16 +- editor/import/resource_importer_obj.cpp | 2 +- editor/import/resource_importer_scene.cpp | 26 +- editor/import/resource_importer_scene.h | 5 +- editor/plugins/spatial_editor_plugin.cpp | 4 +- editor/plugins/spatial_editor_plugin.h | 8 +- editor/spatial_editor_gizmos.cpp | 18 +- editor/spatial_editor_gizmos.h | 8 +- scene/3d/gi_probe.cpp | 8 +- scene/3d/gi_probe.h | 4 +- scene/3d/listener.cpp | 2 +- scene/3d/navigation_mesh.cpp | 2 +- scene/3d/navigation_mesh.h | 2 +- scene/3d/ray_cast.cpp | 4 +- scene/main/scene_main_loop.cpp | 4 +- scene/main/scene_main_loop.h | 5 +- scene/register_scene_types.cpp | 5 +- scene/resources/mesh.cpp | 1402 +++++++++++++++-------------- scene/resources/mesh.h | 51 +- scene/resources/mesh_data_tool.cpp | 6 +- scene/resources/mesh_data_tool.h | 4 +- scene/resources/shape.cpp | 4 +- scene/resources/shape.h | 6 +- scene/resources/surface_tool.cpp | 6 +- scene/resources/surface_tool.h | 2 +- servers/visual/shader_types.cpp | 1 + 27 files changed, 823 insertions(+), 783 deletions(-) diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 4f741c6b7a..b1f7b4c9bd 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -747,6 +747,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom"; actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; actions[VS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture"; + actions[VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_buffer"; actions[VS::SHADER_SPATIAL].renames["SIDE"] = "side"; actions[VS::SHADER_SPATIAL].usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n"; diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 907c7b045c..e0a2ea624e 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -72,7 +72,7 @@ struct ColladaImport { Map node_map; //map from collada node to engine node Map node_name_map; //map from collada node to engine node - Map > mesh_cache; + Map > mesh_cache; Map > curve_cache; Map > material_cache; Map skeleton_map; @@ -88,7 +88,7 @@ struct ColladaImport { Error _create_scene(Collada::Node *p_node, Spatial *p_parent); Error _create_resources(Collada::Node *p_node); Error _create_material(const String &p_material); - Error _create_mesh_surfaces(bool p_optimize, Ref &p_mesh, const Map &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector &bone_remap, const Collada::SkinControllerData *p_skin_data, const Collada::MorphControllerData *p_morph_data, Vector > p_morph_meshes = Vector >(), bool p_for_morph = false, bool p_use_mesh_material = false); + Error _create_mesh_surfaces(bool p_optimize, Ref &p_mesh, const Map &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector &bone_remap, const Collada::SkinControllerData *p_skin_data, const Collada::MorphControllerData *p_morph_data, Vector > p_morph_meshes = Vector >(), bool p_for_morph = false, bool p_use_mesh_material = false); Error load(const String &p_path, int p_flags, bool p_force_make_tangents = false); void _fix_param_animation_tracks(); void create_animation(int p_clip, bool p_make_tracks_in_all_bones, bool p_import_value_tracks); @@ -591,7 +591,7 @@ static void _generate_tangents_and_binormals(const PoolVector &p_indices, c } } -Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref &p_mesh, const Map &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector &bone_remap, const Collada::SkinControllerData *skin_controller, const Collada::MorphControllerData *p_morph_data, Vector > p_morph_meshes, bool p_for_morph, bool p_use_mesh_material) { +Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref &p_mesh, const Map &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector &bone_remap, const Collada::SkinControllerData *skin_controller, const Collada::MorphControllerData *p_morph_data, Vector > p_morph_meshes, bool p_for_morph, bool p_use_mesh_material) { bool local_xform_mirror = p_local_xform.basis.determinant() < 0; @@ -1530,7 +1530,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) { String meshid; Transform apply_xform; Vector bone_remap; - Vector > morphs; + Vector > morphs; print_line("mesh: " + String(mi->get_name())); @@ -1621,9 +1621,9 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) { String meshid = names[i]; if (collada.state.mesh_data_map.has(meshid)) { - Ref mesh = Ref(memnew(Mesh)); + Ref mesh = Ref(memnew(ArrayMesh)); const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid]; - Error err = _create_mesh_surfaces(false, mesh, ng->material_map, meshdata, apply_xform, bone_remap, skin, NULL, Vector >(), true); + Error err = _create_mesh_surfaces(false, mesh, ng->material_map, meshdata, apply_xform, bone_remap, skin, NULL, Vector >(), true); ERR_FAIL_COND_V(err, err); morphs.push_back(mesh); @@ -1648,7 +1648,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) { meshid = ng->source; } - Ref mesh; + Ref mesh; if (mesh_cache.has(meshid)) { mesh = mesh_cache[meshid]; } else { @@ -1656,7 +1656,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) { //bleh, must ignore invalid ERR_FAIL_COND_V(!collada.state.mesh_data_map.has(meshid), ERR_INVALID_DATA); - mesh = Ref(memnew(Mesh)); + mesh = Ref(memnew(ArrayMesh)); const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid]; mesh->set_name(meshdata.name); Error err = _create_mesh_surfaces(morphs.size() == 0, mesh, ng->material_map, meshdata, apply_xform, bone_remap, skin, morph, morphs, false, use_mesh_builtin_materials); diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index 21c2ae6eb3..8d0f3267f7 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -89,7 +89,7 @@ Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_s FileAccessRef f = FileAccess::open(p_source_file, FileAccess::READ); ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); - Ref mesh = Ref(memnew(Mesh)); + Ref mesh = Ref(memnew(ArrayMesh)); Map > name_map; bool generate_normals = p_options["generate/normals"]; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 755f4eb219..d2d2d45a47 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -137,7 +137,7 @@ static String _fixstr(const String &p_what, const String &p_str) { return p_what; } -Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map, Ref > &collision_map) { +Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map, Ref > &collision_map) { // children first.. for (int i = 0; i < p_node->get_child_count(); i++) { @@ -175,7 +175,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map mi->set_flag(GeometryInstance::FLAG_BILLBOARD, true); if (mi->get_mesh().is_valid()) { - Ref m = mi->get_mesh(); + Ref m = mi->get_mesh(); for (int i = 0; i < m->get_surface_count(); i++) { Ref fm = m->surface_get_material(i); @@ -194,7 +194,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map MeshInstance *mi = p_node->cast_to(); - Ref m = mi->get_mesh(); + Ref m = mi->get_mesh(); if (m.is_valid()) { @@ -275,7 +275,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map if (mi->get_mesh().is_valid()) { - Ref m = mi->get_mesh(); + Ref m = mi->get_mesh(); for (int i = 0; i < m->get_surface_count(); i++) { Ref fm = m->surface_get_material(i); @@ -325,7 +325,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map /*if (mi->get_mesh().is_valid()) { - Ref m = mi->get_mesh(); + Ref m = mi->get_mesh(); for(int i=0;iget_surface_count();i++) { Ref fm = m->surface_get_material(i); @@ -477,7 +477,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map MeshInstance *mi = p_node->cast_to(); - Ref mesh = mi->get_mesh(); + Ref mesh = mi->get_mesh(); ERR_FAIL_COND_V(mesh.is_null(), NULL); NavigationMeshInstance *nmi = memnew(NavigationMeshInstance); @@ -655,7 +655,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map MeshInstance *mi = p_node->cast_to(); - Ref mesh = mi->get_mesh(); + Ref mesh = mi->get_mesh(); if (!mesh.is_null()) { if (_teststr(mesh->get_name(), "col")) { @@ -972,7 +972,7 @@ static String _make_extname(const String &p_str) { return ext_name; } -void ResourceImporterScene::_make_external_resources(Node *p_node, const String &p_base_path, bool p_make_materials, bool p_make_meshes, Map, Ref > &p_materials, Map, Ref > &p_meshes) { +void ResourceImporterScene::_make_external_resources(Node *p_node, const String &p_base_path, bool p_make_materials, bool p_make_meshes, Map, Ref > &p_materials, Map, Ref > &p_meshes) { List pi; @@ -1005,7 +1005,7 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String } } else { - Ref mesh = p_node->get(E->get().name); + Ref mesh = p_node->get(E->get().name); if (mesh.is_valid()) { @@ -1018,7 +1018,7 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String String ext_name = p_base_path + "." + _make_extname(mesh->get_name()) + ".msh"; if (FileAccess::exists(ext_name)) { //if exists, use it - Ref existing = ResourceLoader::load(ext_name); + Ref existing = ResourceLoader::load(ext_name); p_meshes[mesh] = existing; } else { @@ -1059,7 +1059,7 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String } if (!p_make_meshes) { - p_meshes[mesh] = Ref(); //save it anyway, so it won't be checked again + p_meshes[mesh] = Ref(); //save it anyway, so it won't be checked again } } } @@ -1192,7 +1192,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p float anim_optimizer_angerr = p_options["animation/optimizer/max_angular_error"]; float anim_optimizer_maxang = p_options["animation/optimizer/max_angle"]; - Map, Ref > collision_map; + Map, Ref > collision_map; scene = _fix_node(scene, scene, collision_map); @@ -1230,7 +1230,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p if (external_materials || external_meshes) { Map, Ref > mat_map; - Map, Ref > mesh_map; + Map, Ref > mesh_map; _make_external_resources(scene, p_source_file.get_basename(), external_materials, external_meshes, mat_map, mesh_map); } diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 9f7b1a84e6..ede3028b29 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -32,6 +32,7 @@ #include "io/resource_import.h" #include "scene/resources/animation.h" +#include "scene/resources/mesh.h" #include "scene/resources/shape.h" class Material; @@ -100,9 +101,9 @@ public: virtual void get_import_options(List *r_options, int p_preset = 0) const; virtual bool get_option_visibility(const String &p_option, const Map &p_options) const; - void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_materials, bool p_make_meshes, Map, Ref > &p_materials, Map, Ref > &p_meshes); + void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_materials, bool p_make_meshes, Map, Ref > &p_materials, Map, Ref > &p_meshes); - Node *_fix_node(Node *p_node, Node *p_root, Map, Ref > &collision_map); + Node *_fix_node(Node *p_node, Node *p_root, Map, Ref > &collision_map); void _create_clips(Node *scene, const Array &p_clips, bool p_bake_all); void _filter_anim_tracks(Ref anim, Set &keep); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 3536ecd094..61f6880433 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -3055,8 +3055,8 @@ void SpatialEditor::_init_indicators() { for (int i = 0; i < 3; i++) { - move_gizmo[i] = Ref(memnew(Mesh)); - rotate_gizmo[i] = Ref(memnew(Mesh)); + move_gizmo[i] = Ref(memnew(ArrayMesh)); + rotate_gizmo[i] = Ref(memnew(ArrayMesh)); Ref mat = memnew(SpatialMaterial); mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 88245ad0dc..394002db3b 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -330,13 +330,13 @@ private: bool grid_enable[3]; //should be always visible if true bool grid_enabled; - Ref move_gizmo[3], rotate_gizmo[3]; + Ref move_gizmo[3], rotate_gizmo[3]; Ref gizmo_color[3]; Ref gizmo_hl; int over_gizmo_handle; - Ref selection_box; + Ref selection_box; RID indicators; RID indicators_instance; RID cursor_mesh; @@ -472,8 +472,8 @@ public: float get_rotate_snap() const { return snap_rotate->get_text().to_double(); } float get_scale_snap() const { return snap_scale->get_text().to_double(); } - Ref get_move_gizmo(int idx) const { return move_gizmo[idx]; } - Ref get_rotate_gizmo(int idx) const { return rotate_gizmo[idx]; } + Ref get_move_gizmo(int idx) const { return move_gizmo[idx]; } + Ref get_rotate_gizmo(int idx) const { return rotate_gizmo[idx]; } void update_transform_gizmo(); diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index 4781bb6a3b..149b06e50a 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -79,7 +79,7 @@ void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base) { VS::get_singleton()->instance_set_layer_mask(instance, 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER); //gizmos are 26 } -void EditorSpatialGizmo::add_mesh(const Ref &p_mesh, bool p_billboard, const RID &p_skeleton) { +void EditorSpatialGizmo::add_mesh(const Ref &p_mesh, bool p_billboard, const RID &p_skeleton) { ERR_FAIL_COND(!spatial_node); Instance ins; @@ -100,7 +100,7 @@ void EditorSpatialGizmo::add_lines(const Vector &p_lines, const Ref mesh = memnew(Mesh); + Ref mesh = memnew(ArrayMesh); Array a; a.resize(Mesh::ARRAY_MAX); @@ -162,7 +162,7 @@ void EditorSpatialGizmo::add_unscaled_billboard(const Ref &p_material, uv.push_back(Vector2(0, 1)); uv.push_back(Vector2(1, 1)); - Ref mesh = memnew(Mesh); + Ref mesh = memnew(ArrayMesh); Array a; a.resize(Mesh::ARRAY_MAX); a[Mesh::ARRAY_VERTEX] = vs; @@ -219,7 +219,7 @@ void EditorSpatialGizmo::add_handles(const Vector &p_handles, bool p_bi ERR_FAIL_COND(!spatial_node); Instance ins; - Ref mesh = memnew(Mesh); + Ref mesh = memnew(ArrayMesh); #if 1 Array a; @@ -1029,7 +1029,7 @@ CameraSpatialGizmo::CameraSpatialGizmo(Camera *p_camera) { void MeshInstanceSpatialGizmo::redraw() { - Ref m = mesh->get_mesh(); + Ref m = mesh->get_mesh(); if (!m.is_valid()) return; //none @@ -1248,7 +1248,7 @@ void SkeletonSpatialGizmo::redraw() { */ } - Ref m = surface_tool->commit(); + Ref m = surface_tool->commit(); add_mesh(m, false, skel->get_skeleton()); } @@ -2511,7 +2511,7 @@ void NavigationMeshSpatialGizmo::redraw() { if (lines.size()) add_lines(lines, navmesh->is_enabled() ? SpatialEditorGizmos::singleton->navmesh_edge_material : SpatialEditorGizmos::singleton->navmesh_edge_material_disabled); add_collision_triangles(tmesh); - Ref m = memnew(Mesh); + Ref m = memnew(ArrayMesh); Array a; a.resize(Mesh::ARRAY_MAX); a[0] = tmeshfaces; @@ -3213,7 +3213,7 @@ SpatialEditorGizmos::SpatialEditorGizmos() { //position 3D Shared mesh - pos3d_mesh = Ref(memnew(Mesh)); + pos3d_mesh = Ref(memnew(ArrayMesh)); { PoolVector cursor_points; @@ -3246,7 +3246,7 @@ SpatialEditorGizmos::SpatialEditorGizmos() { pos3d_mesh->surface_set_material(0, mat); } - listener_line_mesh = Ref(memnew(Mesh)); + listener_line_mesh = Ref(memnew(ArrayMesh)); { PoolVector cursor_points; diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h index 095586ab91..6a77e91425 100644 --- a/editor/spatial_editor_gizmos.h +++ b/editor/spatial_editor_gizmos.h @@ -59,7 +59,7 @@ class EditorSpatialGizmo : public SpatialEditorGizmo { struct Instance { RID instance; - Ref mesh; + Ref mesh; RID skeleton; bool billboard; bool unscaled; @@ -97,7 +97,7 @@ class EditorSpatialGizmo : public SpatialEditorGizmo { protected: void add_lines(const Vector &p_lines, const Ref &p_material, bool p_billboard = false); - void add_mesh(const Ref &p_mesh, bool p_billboard = false, const RID &p_skeleton = RID()); + void add_mesh(const Ref &p_mesh, bool p_billboard = false, const RID &p_skeleton = RID()); void add_collision_segments(const Vector &p_lines); void add_collision_triangles(const Ref &p_tmesh); void add_unscaled_billboard(const Ref &p_material, float p_scale = 1); @@ -454,8 +454,8 @@ public: Ref shape_material; Ref handle_t; - Ref pos3d_mesh; - Ref listener_line_mesh; + Ref pos3d_mesh; + Ref listener_line_mesh; static SpatialEditorGizmos *singleton; Ref test_cube_tm; diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index 2acbed3b4e..ec3e059249 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -973,7 +973,7 @@ GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref p_mater return mc; } -void GIProbe::_plot_mesh(const Transform &p_xform, Ref &p_mesh, Baker *p_baker, const Vector > &p_materials, const Ref &p_override_material) { +void GIProbe::_plot_mesh(const Transform &p_xform, Ref &p_mesh, Baker *p_baker, const Vector > &p_materials, const Ref &p_override_material) { for (int i = 0; i < p_mesh->get_surface_count(); i++) { @@ -1067,7 +1067,7 @@ void GIProbe::_find_meshes(Node *p_at_node, Baker *p_baker) { MeshInstance *mi = p_at_node->cast_to(); if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT)) { - Ref mesh = mi->get_mesh(); + Ref mesh = mi->get_mesh(); if (mesh.is_valid()) { Rect3 aabb = mesh->get_aabb(); @@ -1094,7 +1094,7 @@ void GIProbe::_find_meshes(Node *p_at_node, Baker *p_baker) { for (int i = 0; i < meshes.size(); i += 2) { Transform mxf = meshes[i]; - Ref mesh = meshes[i + 1]; + Ref mesh = meshes[i + 1]; if (!mesh.is_valid()) continue; @@ -1317,7 +1317,7 @@ void GIProbe::_create_debug_mesh(Baker *p_baker) { print_line("leaf voxels: " + itos(p_baker->leaf_voxel_count)); mm->set_instance_count(p_baker->leaf_voxel_count); - Ref mesh; + Ref mesh; mesh.instance(); { diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h index 3b05d9952b..b5ee86455e 100644 --- a/scene/3d/gi_probe.h +++ b/scene/3d/gi_probe.h @@ -145,7 +145,7 @@ private: struct PlotMesh { Ref override_material; Vector > instance_materials; - Ref mesh; + Ref mesh; Transform local_xform; }; @@ -173,7 +173,7 @@ private: Vector _get_bake_texture(Ref p_image, const Color &p_color); Baker::MaterialCache _get_material_cache(Ref p_material, Baker *p_baker); void _plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector2 *p_uv, const Baker::MaterialCache &p_material, const Rect3 &p_aabb, Baker *p_baker); - void _plot_mesh(const Transform &p_xform, Ref &p_mesh, Baker *p_baker, const Vector > &p_materials, const Ref &p_override_material); + void _plot_mesh(const Transform &p_xform, Ref &p_mesh, Baker *p_baker, const Vector > &p_materials, const Ref &p_override_material); void _find_meshes(Node *p_at_node, Baker *p_baker); void _fixup_plot(int p_idx, int p_level, int p_x, int p_y, int p_z, Baker *p_baker); diff --git a/scene/3d/listener.cpp b/scene/3d/listener.cpp index 148afbffa2..c7d3bac2f8 100644 --- a/scene/3d/listener.cpp +++ b/scene/3d/listener.cpp @@ -152,7 +152,7 @@ bool Listener::_can_gizmo_scale() const { } RES Listener::_get_gizmo_geometry() const { - Ref mesh = memnew(Mesh); + Ref mesh = memnew(ArrayMesh); return mesh; } diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp index 13fd852fe7..82f6f665db 100644 --- a/scene/3d/navigation_mesh.cpp +++ b/scene/3d/navigation_mesh.cpp @@ -187,7 +187,7 @@ Ref NavigationMesh::get_debug_mesh() { } } - debug_mesh = Ref(memnew(Mesh)); + debug_mesh = Ref(memnew(ArrayMesh)); Array arr; arr.resize(Mesh::ARRAY_MAX); diff --git a/scene/3d/navigation_mesh.h b/scene/3d/navigation_mesh.h index c8f6d936aa..e5a3dc7b43 100644 --- a/scene/3d/navigation_mesh.h +++ b/scene/3d/navigation_mesh.h @@ -44,7 +44,7 @@ class NavigationMesh : public Resource { Vector indices; }; Vector polygons; - Ref debug_mesh; + Ref debug_mesh; struct _EdgeKey { diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp index d24aa6ae2a..345afd3edf 100644 --- a/scene/3d/ray_cast.cpp +++ b/scene/3d/ray_cast.cpp @@ -266,7 +266,7 @@ void RayCast::_create_debug_shape() { line_material->set_albedo(Color(1.0, 0.8, 0.6)); } - Ref mesh = memnew(Mesh); + Ref mesh = memnew(ArrayMesh); MeshInstance *mi = memnew(MeshInstance); mi->set_mesh(mesh); @@ -287,7 +287,7 @@ void RayCast::_update_debug_shape() { if (!mi->get_mesh().is_valid()) return; - Ref mesh = mi->get_mesh(); + Ref mesh = mi->get_mesh(); if (mesh->get_surface_count() > 0) mesh->surface_remove(0); diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp index 96a3519840..f7a255cd33 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_main_loop.cpp @@ -839,12 +839,12 @@ Ref SceneTree::get_debug_collision_material() { return collision_material; } -Ref SceneTree::get_debug_contact_mesh() { +Ref SceneTree::get_debug_contact_mesh() { if (debug_contact_mesh.is_valid()) return debug_contact_mesh; - debug_contact_mesh = Ref(memnew(Mesh)); + debug_contact_mesh = Ref(memnew(ArrayMesh)); Ref mat = memnew(SpatialMaterial); /*mat->set_flag(Material::FLAG_UNSHADED,true); diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h index 5d42c66652..2ea79bf945 100644 --- a/scene/main/scene_main_loop.h +++ b/scene/main/scene_main_loop.h @@ -33,6 +33,7 @@ #include "io/networked_multiplayer_peer.h" #include "os/main_loop.h" #include "os/thread_safe.h" +#include "scene/resources/mesh.h" #include "scene/resources/world.h" #include "scene/resources/world_2d.h" #include "self_list.h" @@ -169,7 +170,7 @@ private: Color debug_collision_contact_color; Color debug_navigation_color; Color debug_navigation_disabled_color; - Ref debug_contact_mesh; + Ref debug_contact_mesh; Ref navigation_material; Ref navigation_disabled_material; Ref collision_material; @@ -406,7 +407,7 @@ public: Ref get_debug_navigation_material(); Ref get_debug_navigation_disabled_material(); Ref get_debug_collision_material(); - Ref get_debug_contact_mesh(); + Ref get_debug_contact_mesh(); int get_collision_debug_contact_count() { return collision_debug_contacts; } diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 0a3f64eacd..9f078072d7 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -523,11 +523,12 @@ void register_scene_types() { ClassDB::register_virtual_class(); #ifndef _3D_DISABLED - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_virtual_class(); + ClassDB::register_class(); ClassDB::register_virtual_class(); ClassDB::register_class(); ClassDB::add_compatibility_class("FixedSpatialMaterial", "SpatialMaterial"); + ClassDB::add_compatibility_class("Mesh", "ArrayMesh"); SceneTree::add_idle_callback(SpatialMaterial::flush_changes); SpatialMaterial::init_shaders(); diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 4846d84b33..e2ede41290 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -32,968 +32,977 @@ #include "scene/resources/convex_polygon_shape.h" #include "surface_tool.h" -static const char *_array_name[] = { - "vertex_array", - "normal_array", - "tangent_array", - "color_array", - "tex_uv_array", - "tex_uv2_array", - "bone_array", - "weights_array", - "index_array", - NULL -}; +void Mesh::_clear_triangle_mesh() { -static const Mesh::ArrayType _array_types[] = { - - Mesh::ARRAY_VERTEX, - Mesh::ARRAY_NORMAL, - Mesh::ARRAY_TANGENT, - Mesh::ARRAY_COLOR, - Mesh::ARRAY_TEX_UV, - Mesh::ARRAY_TEX_UV2, - Mesh::ARRAY_BONES, - Mesh::ARRAY_WEIGHTS, - Mesh::ARRAY_INDEX -}; + triangle_mesh.unref(); + ; +} -/* compatibility */ -static const int _format_translate[] = { +Ref Mesh::generate_triangle_mesh() const { - Mesh::ARRAY_FORMAT_VERTEX, - Mesh::ARRAY_FORMAT_NORMAL, - Mesh::ARRAY_FORMAT_TANGENT, - Mesh::ARRAY_FORMAT_COLOR, - Mesh::ARRAY_FORMAT_TEX_UV, - Mesh::ARRAY_FORMAT_TEX_UV2, - Mesh::ARRAY_FORMAT_BONES, - Mesh::ARRAY_FORMAT_WEIGHTS, - Mesh::ARRAY_FORMAT_INDEX, -}; + if (triangle_mesh.is_valid()) + return triangle_mesh; -bool Mesh::_set(const StringName &p_name, const Variant &p_value) { + int facecount = 0; - String sname = p_name; + for (int i = 0; i < get_surface_count(); i++) { - if (p_name == "blend_shape/names") { + if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) + continue; - PoolVector sk = p_value; - int sz = sk.size(); - PoolVector::Read r = sk.read(); - for (int i = 0; i < sz; i++) - add_blend_shape(r[i]); - return true; - } + if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { - if (p_name == "blend_shape/mode") { + facecount += surface_get_array_index_len(i); + } else { - set_blend_shape_mode(BlendShapeMode(int(p_value))); - return true; + facecount += surface_get_array_len(i); + } } - if (sname.begins_with("surface_")) { + if (facecount == 0 || (facecount % 3) != 0) + return triangle_mesh; - int sl = sname.find("/"); - if (sl == -1) - return false; - int idx = sname.substr(8, sl - 8).to_int() - 1; - String what = sname.get_slicec('/', 1); - if (what == "material") - surface_set_material(idx, p_value); - else if (what == "name") - surface_set_name(idx, p_value); - return true; - } + PoolVector faces; + faces.resize(facecount); + PoolVector::Write facesw = faces.write(); - if (sname == "custom_aabb/custom_aabb") { + int widx = 0; - set_custom_aabb(p_value); - return true; - } + for (int i = 0; i < get_surface_count(); i++) { - if (!sname.begins_with("surfaces")) - return false; + if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) + continue; - int idx = sname.get_slicec('/', 1).to_int(); - String what = sname.get_slicec('/', 2); + Array a = surface_get_arrays(i); - if (idx == surfaces.size()) { + int vc = surface_get_array_len(i); + PoolVector vertices = a[ARRAY_VERTEX]; + PoolVector::Read vr = vertices.read(); - //create - Dictionary d = p_value; - ERR_FAIL_COND_V(!d.has("primitive"), false); + if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { - if (d.has("arrays")) { - //old format - ERR_FAIL_COND_V(!d.has("morph_arrays"), false); - add_surface_from_arrays(PrimitiveType(int(d["primitive"])), d["arrays"], d["morph_arrays"]); + int ic = surface_get_array_index_len(i); + PoolVector indices = a[ARRAY_INDEX]; + PoolVector::Read ir = indices.read(); - } else if (d.has("array_data")) { + for (int i = 0; i < ic; i++) { + int index = ir[i]; + facesw[widx++] = vr[index]; + } - PoolVector array_data = d["array_data"]; - PoolVector array_index_data; - if (d.has("array_index_data")) - array_index_data = d["array_index_data"]; + } else { - ERR_FAIL_COND_V(!d.has("format"), false); - uint32_t format = d["format"]; + for (int i = 0; i < vc; i++) + facesw[widx++] = vr[i]; + } + } - ERR_FAIL_COND_V(!d.has("primitive"), false); - uint32_t primitive = d["primitive"]; + facesw = PoolVector::Write(); - ERR_FAIL_COND_V(!d.has("vertex_count"), false); - int vertex_count = d["vertex_count"]; + triangle_mesh = Ref(memnew(TriangleMesh)); + triangle_mesh->create(faces); - int index_count = 0; - if (d.has("index_count")) - index_count = d["index_count"]; + return triangle_mesh; +} - Vector > blend_shapes; +PoolVector Mesh::get_faces() const { - if (d.has("blend_shape_data")) { - Array blend_shape_data = d["blend_shape_data"]; - for (int i = 0; i < blend_shape_data.size(); i++) { - PoolVector shape = blend_shape_data[i]; - blend_shapes.push_back(shape); - } - } + Ref tm = generate_triangle_mesh(); + if (tm.is_valid()) + return tm->get_faces(); + return PoolVector(); + /* + for (int i=0;imesh_surface_get_primitive_type( mesh, i ) != VisualServer::PRIMITIVE_TRIANGLES ) + continue; - Vector bone_aabb; - if (d.has("bone_aabb")) { - Array baabb = d["bone_aabb"]; - bone_aabb.resize(baabb.size()); + PoolVector indices; + PoolVector vertices; - for (int i = 0; i < baabb.size(); i++) { - bone_aabb[i] = baabb[i]; - } - } + vertices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_VERTEX); - add_surface(format, PrimitiveType(primitive), array_data, vertex_count, array_index_data, index_count, aabb, blend_shapes, bone_aabb); - } else { - ERR_FAIL_V(false); - } + int len=VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, i); + bool has_indices; - if (d.has("material")) { + if (len>0) { - surface_set_material(idx, d["material"]); - } - if (d.has("name")) { - surface_set_name(idx, d["name"]); - } + indices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_INDEX); + has_indices=true; - return true; - } + } else { - return false; -} + len=vertices.size(); + has_indices=false; + } -bool Mesh::_get(const StringName &p_name, Variant &r_ret) const { + if (len<=0) + continue; - if (_is_generated()) - return false; + PoolVector::Read indicesr = indices.read(); + const int *indicesptr = indicesr.ptr(); - String sname = p_name; + PoolVector::Read verticesr = vertices.read(); + const Vector3 *verticesptr = verticesr.ptr(); - if (p_name == "blend_shape/names") { + int old_faces=faces.size(); + int new_faces=old_faces+(len/3); - PoolVector sk; - for (int i = 0; i < blend_shapes.size(); i++) - sk.push_back(blend_shapes[i]); - r_ret = sk; - return true; - } else if (p_name == "blend_shape/mode") { + faces.resize(new_faces); - r_ret = get_blend_shape_mode(); - return true; - } else if (sname.begins_with("surface_")) { + PoolVector::Write facesw = faces.write(); + Face3 *facesptr=facesw.ptr(); - int sl = sname.find("/"); - if (sl == -1) - return false; - int idx = sname.substr(8, sl - 8).to_int() - 1; - String what = sname.get_slicec('/', 1); - if (what == "material") - r_ret = surface_get_material(idx); - else if (what == "name") - r_ret = surface_get_name(idx); - return true; - } else if (sname == "custom_aabb/custom_aabb") { - r_ret = custom_aabb; - return true; + for (int i=0;imesh_surface_get_array(mesh, idx); - d["vertex_count"] = VS::get_singleton()->mesh_surface_get_array_len(mesh, idx); - d["array_index_data"] = VS::get_singleton()->mesh_surface_get_index_array(mesh, idx); - d["index_count"] = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, idx); - d["primitive"] = VS::get_singleton()->mesh_surface_get_primitive_type(mesh, idx); - d["format"] = VS::get_singleton()->mesh_surface_get_format(mesh, idx); - d["aabb"] = VS::get_singleton()->mesh_surface_get_aabb(mesh, idx); + facesptr[i+old_faces]=face; + } - Vector skel_aabb = VS::get_singleton()->mesh_surface_get_skeleton_aabb(mesh, idx); - Array arr; - for (int i = 0; i < skel_aabb.size(); i++) { - arr[i] = skel_aabb[i]; } - d["skeleton_aabb"] = arr; - - Vector > blend_shape_data = VS::get_singleton()->mesh_surface_get_blend_shapes(mesh, idx); +*/ +} - Array md; - for (int i = 0; i < blend_shape_data.size(); i++) { - md.push_back(blend_shape_data[i]); - } +Ref Mesh::create_convex_shape() const { - d["blend_shape_data"] = md; + PoolVector vertices; - Ref m = surface_get_material(idx); - if (m.is_valid()) - d["material"] = m; - String n = surface_get_name(idx); - if (n != "") - d["name"] = n; + for (int i = 0; i < get_surface_count(); i++) { - r_ret = d; + Array a = surface_get_arrays(i); + PoolVector v = a[ARRAY_VERTEX]; + vertices.append_array(v); + } - return true; + Ref shape = memnew(ConvexPolygonShape); + shape->set_points(vertices); + return shape; } -void Mesh::_get_property_list(List *p_list) const { +Ref Mesh::create_trimesh_shape() const { - if (_is_generated()) - return; + PoolVector faces = get_faces(); + if (faces.size() == 0) + return Ref(); - if (blend_shapes.size()) { - p_list->push_back(PropertyInfo(Variant::POOL_STRING_ARRAY, "blend_shape/names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::INT, "blend_shape/mode", PROPERTY_HINT_ENUM, "Normalized,Relative")); - } + PoolVector face_points; + face_points.resize(faces.size() * 3); - for (int i = 0; i < surfaces.size(); i++) { + for (int i = 0; i < face_points.size(); i++) { - p_list->push_back(PropertyInfo(Variant::DICTIONARY, "surfaces/" + itos(i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::STRING, "surface_" + itos(i + 1) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "Material", PROPERTY_USAGE_EDITOR)); + Face3 f = faces.get(i / 3); + face_points.set(i, f.vertex[i % 3]); } - p_list->push_back(PropertyInfo(Variant::RECT3, "custom_aabb/custom_aabb")); + Ref shape = memnew(ConcavePolygonShape); + shape->set_faces(face_points); + return shape; } -void Mesh::_recompute_aabb() { +Ref Mesh::create_outline(float p_margin) const { - // regenerate AABB - aabb = Rect3(); + Array arrays; + int index_accum = 0; + for (int i = 0; i < get_surface_count(); i++) { - for (int i = 0; i < surfaces.size(); i++) { + if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) + continue; - if (i == 0) - aabb = surfaces[i].aabb; - else - aabb.merge_with(surfaces[i].aabb); - } -} + Array a = surface_get_arrays(i); + int vcount = 0; -void Mesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector &p_array, int p_vertex_count, const PoolVector &p_index_array, int p_index_count, const Rect3 &p_aabb, const Vector > &p_blend_shapes, const Vector &p_bone_aabbs) { + if (i == 0) { + arrays = a; + PoolVector v = a[ARRAY_VERTEX]; + index_accum += v.size(); + } else { - Surface s; - s.aabb = p_aabb; - surfaces.push_back(s); + for (int j = 0; j < arrays.size(); j++) { - VisualServer::get_singleton()->mesh_add_surface(mesh, p_format, (VS::PrimitiveType)p_primitive, p_array, p_vertex_count, p_index_array, p_index_count, p_aabb, p_blend_shapes, p_bone_aabbs); -} + if (arrays[j].get_type() == Variant::NIL || a[j].get_type() == Variant::NIL) { + //mismatch, do not use + arrays[j] = Variant(); + continue; + } -void Mesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, uint32_t p_flags) { + switch (j) { - ERR_FAIL_COND(p_arrays.size() != ARRAY_MAX); + case ARRAY_VERTEX: + case ARRAY_NORMAL: { - Surface s; + PoolVector dst = arrays[j]; + PoolVector src = a[j]; + if (j == ARRAY_VERTEX) + vcount = src.size(); + if (dst.size() == 0 || src.size() == 0) { + arrays[j] = Variant(); + continue; + } + dst.append_array(src); + arrays[j] = dst; + } break; + case ARRAY_TANGENT: + case ARRAY_BONES: + case ARRAY_WEIGHTS: { - VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (VisualServer::PrimitiveType)p_primitive, p_arrays, p_blend_shapes, p_flags); - surfaces.push_back(s); + PoolVector dst = arrays[j]; + PoolVector src = a[j]; + if (dst.size() == 0 || src.size() == 0) { + arrays[j] = Variant(); + continue; + } + dst.append_array(src); + arrays[j] = dst; - /* make aABB? */ { + } break; + case ARRAY_COLOR: { + PoolVector dst = arrays[j]; + PoolVector src = a[j]; + if (dst.size() == 0 || src.size() == 0) { + arrays[j] = Variant(); + continue; + } + dst.append_array(src); + arrays[j] = dst; - PoolVector vertices = p_arrays[ARRAY_VERTEX]; - int len = vertices.size(); - ERR_FAIL_COND(len == 0); - PoolVector::Read r = vertices.read(); - const Vector3 *vtx = r.ptr(); + } break; + case ARRAY_TEX_UV: + case ARRAY_TEX_UV2: { + PoolVector dst = arrays[j]; + PoolVector src = a[j]; + if (dst.size() == 0 || src.size() == 0) { + arrays[j] = Variant(); + continue; + } + dst.append_array(src); + arrays[j] = dst; - // check AABB - Rect3 aabb; - for (int i = 0; i < len; i++) { + } break; + case ARRAY_INDEX: { + PoolVector dst = arrays[j]; + PoolVector src = a[j]; + if (dst.size() == 0 || src.size() == 0) { + arrays[j] = Variant(); + continue; + } + { + int ss = src.size(); + PoolVector::Write w = src.write(); + for (int k = 0; k < ss; k++) { + w[k] += index_accum; + } + } + dst.append_array(src); + arrays[j] = dst; + index_accum += vcount; - if (i == 0) - aabb.pos = vtx[i]; - else - aabb.expand_to(vtx[i]); + } break; + } + } } + } - surfaces[surfaces.size() - 1].aabb = aabb; + { + PoolVector::Write ir; + PoolVector indices = arrays[ARRAY_INDEX]; + bool has_indices = false; + PoolVector vertices = arrays[ARRAY_VERTEX]; + int vc = vertices.size(); + ERR_FAIL_COND_V(!vc, Ref()); + PoolVector::Write r = vertices.write(); - _recompute_aabb(); - } + if (indices.size()) { + vc = indices.size(); + ir = indices.write(); + has_indices = true; + } - triangle_mesh = Ref(); - _change_notify(); - emit_changed(); -} + Map normal_accum; -Array Mesh::surface_get_arrays(int p_surface) const { + //fill normals with triangle normals + for (int i = 0; i < vc; i += 3) { - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); - return VisualServer::get_singleton()->mesh_surface_get_arrays(mesh, p_surface); -} -Array Mesh::surface_get_blend_shape_arrays(int p_surface) const { + Vector3 t[3]; + + if (has_indices) { + t[0] = r[ir[i + 0]]; + t[1] = r[ir[i + 1]]; + t[2] = r[ir[i + 2]]; + } else { + t[0] = r[i + 0]; + t[1] = r[i + 1]; + t[2] = r[i + 2]; + } + + Vector3 n = Plane(t[0], t[1], t[2]).normal; + + for (int j = 0; j < 3; j++) { + + Map::Element *E = normal_accum.find(t[j]); + if (!E) { + normal_accum[t[j]] = n; + } else { + float d = n.dot(E->get()); + if (d < 1.0) + E->get() += n * (1.0 - d); + //E->get()+=n; + } + } + } + + //normalize - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); - return Array(); -} + for (Map::Element *E = normal_accum.front(); E; E = E->next()) { + E->get().normalize(); + } -int Mesh::get_surface_count() const { + //displace normals + int vc2 = vertices.size(); - return surfaces.size(); -} + for (int i = 0; i < vc2; i++) { -void Mesh::add_blend_shape(const StringName &p_name) { + Vector3 t = r[i]; - if (surfaces.size()) { - ERR_EXPLAIN("Can't add a shape key count if surfaces are already created."); - ERR_FAIL_COND(surfaces.size()); - } + Map::Element *E = normal_accum.find(t); + ERR_CONTINUE(!E); - StringName name = p_name; + t += E->get() * p_margin; + r[i] = t; + } - if (blend_shapes.find(name) != -1) { + r = PoolVector::Write(); + arrays[ARRAY_VERTEX] = vertices; - int count = 2; - do { + if (!has_indices) { - name = String(p_name) + " " + itos(count); - count++; - } while (blend_shapes.find(name) != -1); - } + PoolVector new_indices; + new_indices.resize(vertices.size()); + PoolVector::Write iw = new_indices.write(); - blend_shapes.push_back(name); - VS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size()); -} + for (int j = 0; j < vc2; j += 3) { -int Mesh::get_blend_shape_count() const { + iw[j] = j; + iw[j + 1] = j + 2; + iw[j + 2] = j + 1; + } - return blend_shapes.size(); -} -StringName Mesh::get_blend_shape_name(int p_index) const { - ERR_FAIL_INDEX_V(p_index, blend_shapes.size(), StringName()); - return blend_shapes[p_index]; -} -void Mesh::clear_blend_shapes() { + iw = PoolVector::Write(); + arrays[ARRAY_INDEX] = new_indices; - if (surfaces.size()) { - ERR_EXPLAIN("Can't set shape key count if surfaces are already created."); - ERR_FAIL_COND(surfaces.size()); - } + } else { - blend_shapes.clear(); -} + for (int j = 0; j < vc; j += 3) { -void Mesh::set_blend_shape_mode(BlendShapeMode p_mode) { + SWAP(ir[j + 1], ir[j + 2]); + } + ir = PoolVector::Write(); + arrays[ARRAY_INDEX] = indices; + } + } - blend_shape_mode = p_mode; - VS::get_singleton()->mesh_set_blend_shape_mode(mesh, (VS::BlendShapeMode)p_mode); + Ref newmesh = memnew(ArrayMesh); + newmesh->add_surface_from_arrays(PRIMITIVE_TRIANGLES, arrays); + return newmesh; } -Mesh::BlendShapeMode Mesh::get_blend_shape_mode() const { - - return blend_shape_mode; +Mesh::Mesh() { } -void Mesh::surface_remove(int p_idx) { +static const char *_array_name[] = { + "vertex_array", + "normal_array", + "tangent_array", + "color_array", + "tex_uv_array", + "tex_uv2_array", + "bone_array", + "weights_array", + "index_array", + NULL +}; - ERR_FAIL_INDEX(p_idx, surfaces.size()); - VisualServer::get_singleton()->mesh_remove_surface(mesh, p_idx); - surfaces.remove(p_idx); +static const ArrayMesh::ArrayType _array_types[] = { + + ArrayMesh::ARRAY_VERTEX, + ArrayMesh::ARRAY_NORMAL, + ArrayMesh::ARRAY_TANGENT, + ArrayMesh::ARRAY_COLOR, + ArrayMesh::ARRAY_TEX_UV, + ArrayMesh::ARRAY_TEX_UV2, + ArrayMesh::ARRAY_BONES, + ArrayMesh::ARRAY_WEIGHTS, + ArrayMesh::ARRAY_INDEX +}; - triangle_mesh = Ref(); - _recompute_aabb(); - _change_notify(); - emit_changed(); -} +/* compatibility */ +static const int _format_translate[] = { -int Mesh::surface_get_array_len(int p_idx) const { + ArrayMesh::ARRAY_FORMAT_VERTEX, + ArrayMesh::ARRAY_FORMAT_NORMAL, + ArrayMesh::ARRAY_FORMAT_TANGENT, + ArrayMesh::ARRAY_FORMAT_COLOR, + ArrayMesh::ARRAY_FORMAT_TEX_UV, + ArrayMesh::ARRAY_FORMAT_TEX_UV2, + ArrayMesh::ARRAY_FORMAT_BONES, + ArrayMesh::ARRAY_FORMAT_WEIGHTS, + ArrayMesh::ARRAY_FORMAT_INDEX, +}; - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); - return VisualServer::get_singleton()->mesh_surface_get_array_len(mesh, p_idx); -} +bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { -int Mesh::surface_get_array_index_len(int p_idx) const { + String sname = p_name; - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); - return VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, p_idx); -} + if (p_name == "blend_shape/names") { -uint32_t Mesh::surface_get_format(int p_idx) const { + PoolVector sk = p_value; + int sz = sk.size(); + PoolVector::Read r = sk.read(); + for (int i = 0; i < sz; i++) + add_blend_shape(r[i]); + return true; + } - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), 0); - return VisualServer::get_singleton()->mesh_surface_get_format(mesh, p_idx); -} + if (p_name == "blend_shape/mode") { -Mesh::PrimitiveType Mesh::surface_get_primitive_type(int p_idx) const { + set_blend_shape_mode(BlendShapeMode(int(p_value))); + return true; + } - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), PRIMITIVE_LINES); - return (PrimitiveType)VisualServer::get_singleton()->mesh_surface_get_primitive_type(mesh, p_idx); -} + if (sname.begins_with("surface_")) { -void Mesh::surface_set_material(int p_idx, const Ref &p_material) { + int sl = sname.find("/"); + if (sl == -1) + return false; + int idx = sname.substr(8, sl - 8).to_int() - 1; + String what = sname.get_slicec('/', 1); + if (what == "material") + surface_set_material(idx, p_value); + else if (what == "name") + surface_set_name(idx, p_value); + return true; + } - ERR_FAIL_INDEX(p_idx, surfaces.size()); - if (surfaces[p_idx].material == p_material) - return; - surfaces[p_idx].material = p_material; - VisualServer::get_singleton()->mesh_surface_set_material(mesh, p_idx, p_material.is_null() ? RID() : p_material->get_rid()); + if (sname == "custom_aabb/custom_aabb") { - _change_notify("material"); -} + set_custom_aabb(p_value); + return true; + } -void Mesh::surface_set_name(int p_idx, const String &p_name) { + if (!sname.begins_with("surfaces")) + return false; - ERR_FAIL_INDEX(p_idx, surfaces.size()); + int idx = sname.get_slicec('/', 1).to_int(); + String what = sname.get_slicec('/', 2); - surfaces[p_idx].name = p_name; -} + if (idx == surfaces.size()) { -String Mesh::surface_get_name(int p_idx) const { + //create + Dictionary d = p_value; + ERR_FAIL_COND_V(!d.has("primitive"), false); - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), String()); - return surfaces[p_idx].name; -} + if (d.has("arrays")) { + //old format + ERR_FAIL_COND_V(!d.has("morph_arrays"), false); + add_surface_from_arrays(PrimitiveType(int(d["primitive"])), d["arrays"], d["morph_arrays"]); -void Mesh::surface_set_custom_aabb(int p_idx, const Rect3 &p_aabb) { + } else if (d.has("array_data")) { - ERR_FAIL_INDEX(p_idx, surfaces.size()); - surfaces[p_idx].aabb = p_aabb; - // set custom aabb too? -} + PoolVector array_data = d["array_data"]; + PoolVector array_index_data; + if (d.has("array_index_data")) + array_index_data = d["array_index_data"]; -Ref Mesh::surface_get_material(int p_idx) const { + ERR_FAIL_COND_V(!d.has("format"), false); + uint32_t format = d["format"]; - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), Ref()); - return surfaces[p_idx].material; -} + ERR_FAIL_COND_V(!d.has("primitive"), false); + uint32_t primitive = d["primitive"]; -void Mesh::add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data) { + ERR_FAIL_COND_V(!d.has("vertex_count"), false); + int vertex_count = d["vertex_count"]; - VisualServer::get_singleton()->mesh_add_surface_from_mesh_data(mesh, p_mesh_data); - Rect3 aabb; - for (int i = 0; i < p_mesh_data.vertices.size(); i++) { + int index_count = 0; + if (d.has("index_count")) + index_count = d["index_count"]; - if (i == 0) - aabb.pos = p_mesh_data.vertices[i]; - else - aabb.expand_to(p_mesh_data.vertices[i]); - } + Vector > blend_shapes; - Surface s; - s.aabb = aabb; - if (surfaces.size() == 0) - aabb = s.aabb; - else - aabb.merge_with(s.aabb); + if (d.has("blend_shape_data")) { + Array blend_shape_data = d["blend_shape_data"]; + for (int i = 0; i < blend_shape_data.size(); i++) { + PoolVector shape = blend_shape_data[i]; + blend_shapes.push_back(shape); + } + } - triangle_mesh = Ref(); + ERR_FAIL_COND_V(!d.has("aabb"), false); + Rect3 aabb = d["aabb"]; - surfaces.push_back(s); - _change_notify(); + Vector bone_aabb; + if (d.has("bone_aabb")) { + Array baabb = d["bone_aabb"]; + bone_aabb.resize(baabb.size()); - emit_changed(); -} + for (int i = 0; i < baabb.size(); i++) { + bone_aabb[i] = baabb[i]; + } + } -RID Mesh::get_rid() const { + add_surface(format, PrimitiveType(primitive), array_data, vertex_count, array_index_data, index_count, aabb, blend_shapes, bone_aabb); + } else { + ERR_FAIL_V(false); + } - return mesh; -} -Rect3 Mesh::get_aabb() const { + if (d.has("material")) { - return aabb; -} + surface_set_material(idx, d["material"]); + } + if (d.has("name")) { + surface_set_name(idx, d["name"]); + } -void Mesh::set_custom_aabb(const Rect3 &p_custom) { + return true; + } - custom_aabb = p_custom; - VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); + return false; } -Rect3 Mesh::get_custom_aabb() const { +bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const { - return custom_aabb; -} - -PoolVector Mesh::get_faces() const { + if (_is_generated()) + return false; - Ref tm = generate_triangle_mesh(); - if (tm.is_valid()) - return tm->get_faces(); - return PoolVector(); - /* - for (int i=0;imesh_surface_get_primitive_type( mesh, i ) != VisualServer::PRIMITIVE_TRIANGLES ) - continue; + if (p_name == "blend_shape/names") { - PoolVector indices; - PoolVector vertices; + PoolVector sk; + for (int i = 0; i < blend_shapes.size(); i++) + sk.push_back(blend_shapes[i]); + r_ret = sk; + return true; + } else if (p_name == "blend_shape/mode") { - vertices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_VERTEX); + r_ret = get_blend_shape_mode(); + return true; + } else if (sname.begins_with("surface_")) { - int len=VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, i); - bool has_indices; + int sl = sname.find("/"); + if (sl == -1) + return false; + int idx = sname.substr(8, sl - 8).to_int() - 1; + String what = sname.get_slicec('/', 1); + if (what == "material") + r_ret = surface_get_material(idx); + else if (what == "name") + r_ret = surface_get_name(idx); + return true; + } else if (sname == "custom_aabb/custom_aabb") { - if (len>0) { + r_ret = custom_aabb; + return true; - indices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_INDEX); - has_indices=true; + } else if (!sname.begins_with("surfaces")) + return false; - } else { + int idx = sname.get_slicec('/', 1).to_int(); + ERR_FAIL_INDEX_V(idx, surfaces.size(), false); - len=vertices.size(); - has_indices=false; - } + Dictionary d; - if (len<=0) - continue; + d["array_data"] = VS::get_singleton()->mesh_surface_get_array(mesh, idx); + d["vertex_count"] = VS::get_singleton()->mesh_surface_get_array_len(mesh, idx); + d["array_index_data"] = VS::get_singleton()->mesh_surface_get_index_array(mesh, idx); + d["index_count"] = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, idx); + d["primitive"] = VS::get_singleton()->mesh_surface_get_primitive_type(mesh, idx); + d["format"] = VS::get_singleton()->mesh_surface_get_format(mesh, idx); + d["aabb"] = VS::get_singleton()->mesh_surface_get_aabb(mesh, idx); - PoolVector::Read indicesr = indices.read(); - const int *indicesptr = indicesr.ptr(); + Vector skel_aabb = VS::get_singleton()->mesh_surface_get_skeleton_aabb(mesh, idx); + Array arr; + for (int i = 0; i < skel_aabb.size(); i++) { + arr[i] = skel_aabb[i]; + } + d["skeleton_aabb"] = arr; - PoolVector::Read verticesr = vertices.read(); - const Vector3 *verticesptr = verticesr.ptr(); + Vector > blend_shape_data = VS::get_singleton()->mesh_surface_get_blend_shapes(mesh, idx); - int old_faces=faces.size(); - int new_faces=old_faces+(len/3); + Array md; + for (int i = 0; i < blend_shape_data.size(); i++) { + md.push_back(blend_shape_data[i]); + } - faces.resize(new_faces); + d["blend_shape_data"] = md; - PoolVector::Write facesw = faces.write(); - Face3 *facesptr=facesw.ptr(); + Ref m = surface_get_material(idx); + if (m.is_valid()) + d["material"] = m; + String n = surface_get_name(idx); + if (n != "") + d["name"] = n; + r_ret = d; - for (int i=0;i *p_list) const { - for (int j=0;j<3;j++) { + if (_is_generated()) + return; - int idx=i*3+j; - face.vertex[j] = has_indices ? verticesptr[ indicesptr[ idx ] ] : verticesptr[idx]; - } + if (blend_shapes.size()) { + p_list->push_back(PropertyInfo(Variant::POOL_STRING_ARRAY, "blend_shape/names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::INT, "blend_shape/mode", PROPERTY_HINT_ENUM, "Normalized,Relative")); + } - facesptr[i+old_faces]=face; - } + for (int i = 0; i < surfaces.size(); i++) { + p_list->push_back(PropertyInfo(Variant::DICTIONARY, "surfaces/" + itos(i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::STRING, "surface_" + itos(i + 1) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "Material", PROPERTY_USAGE_EDITOR)); } -*/ + + p_list->push_back(PropertyInfo(Variant::RECT3, "custom_aabb/custom_aabb")); } -Ref Mesh::create_convex_shape() const { +void ArrayMesh::_recompute_aabb() { - PoolVector vertices; + // regenerate AABB + aabb = Rect3(); - for (int i = 0; i < get_surface_count(); i++) { + for (int i = 0; i < surfaces.size(); i++) { - Array a = surface_get_arrays(i); - PoolVector v = a[ARRAY_VERTEX]; - vertices.append_array(v); + if (i == 0) + aabb = surfaces[i].aabb; + else + aabb.merge_with(surfaces[i].aabb); } - - Ref shape = memnew(ConvexPolygonShape); - shape->set_points(vertices); - return shape; } -Ref Mesh::create_trimesh_shape() const { - - PoolVector faces = get_faces(); - if (faces.size() == 0) - return Ref(); +void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector &p_array, int p_vertex_count, const PoolVector &p_index_array, int p_index_count, const Rect3 &p_aabb, const Vector > &p_blend_shapes, const Vector &p_bone_aabbs) { - PoolVector face_points; - face_points.resize(faces.size() * 3); + Surface s; + s.aabb = p_aabb; + surfaces.push_back(s); - for (int i = 0; i < face_points.size(); i++) { + VisualServer::get_singleton()->mesh_add_surface(mesh, p_format, (VS::PrimitiveType)p_primitive, p_array, p_vertex_count, p_index_array, p_index_count, p_aabb, p_blend_shapes, p_bone_aabbs); +} - Face3 f = faces.get(i / 3); - face_points.set(i, f.vertex[i % 3]); - } +void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, uint32_t p_flags) { - Ref shape = memnew(ConcavePolygonShape); - shape->set_faces(face_points); - return shape; -} + ERR_FAIL_COND(p_arrays.size() != ARRAY_MAX); -void Mesh::center_geometry() { + Surface s; - /* - Vector3 ofs = aabb.pos+aabb.size*0.5; + VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (VisualServer::PrimitiveType)p_primitive, p_arrays, p_blend_shapes, p_flags); + surfaces.push_back(s); - for(int i=0;i geom = surface_get_array(i,ARRAY_VERTEX); - int gc =geom.size(); - PoolVector::Write w = geom.write(); - surfaces[i].aabb.pos-=ofs; + PoolVector vertices = p_arrays[ARRAY_VERTEX]; + int len = vertices.size(); + ERR_FAIL_COND(len == 0); + PoolVector::Read r = vertices.read(); + const Vector3 *vtx = r.ptr(); - for(int i=0;i::Write(); - - surface_set_array(i,ARRAY_VERTEX,geom); + surfaces[surfaces.size() - 1].aabb = aabb; + _recompute_aabb(); } - aabb.pos-=ofs; - -*/ + _clear_triangle_mesh(); + _change_notify(); + emit_changed(); } -void Mesh::regen_normalmaps() { +Array ArrayMesh::surface_get_arrays(int p_surface) const { - Vector > surfs; - for (int i = 0; i < get_surface_count(); i++) { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); + return VisualServer::get_singleton()->mesh_surface_get_arrays(mesh, p_surface); +} +Array ArrayMesh::surface_get_blend_shape_arrays(int p_surface) const { - Ref st = memnew(SurfaceTool); - st->create_from(Ref(this), i); - surfs.push_back(st); - } + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); + return Array(); +} - while (get_surface_count()) { - surface_remove(0); - } +int ArrayMesh::get_surface_count() const { - for (int i = 0; i < surfs.size(); i++) { + return surfaces.size(); +} - surfs[i]->generate_tangents(); - surfs[i]->commit(Ref(this)); +void ArrayMesh::add_blend_shape(const StringName &p_name) { + + if (surfaces.size()) { + ERR_EXPLAIN("Can't add a shape key count if surfaces are already created."); + ERR_FAIL_COND(surfaces.size()); } -} -Ref Mesh::generate_triangle_mesh() const { + StringName name = p_name; - if (triangle_mesh.is_valid()) - return triangle_mesh; + if (blend_shapes.find(name) != -1) { - int facecount = 0; + int count = 2; + do { - for (int i = 0; i < get_surface_count(); i++) { + name = String(p_name) + " " + itos(count); + count++; + } while (blend_shapes.find(name) != -1); + } - if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) - continue; + blend_shapes.push_back(name); + VS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size()); +} - if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { +int ArrayMesh::get_blend_shape_count() const { - facecount += surface_get_array_index_len(i); - } else { + return blend_shapes.size(); +} +StringName ArrayMesh::get_blend_shape_name(int p_index) const { + ERR_FAIL_INDEX_V(p_index, blend_shapes.size(), StringName()); + return blend_shapes[p_index]; +} +void ArrayMesh::clear_blend_shapes() { - facecount += surface_get_array_len(i); - } + if (surfaces.size()) { + ERR_EXPLAIN("Can't set shape key count if surfaces are already created."); + ERR_FAIL_COND(surfaces.size()); } - if (facecount == 0 || (facecount % 3) != 0) - return triangle_mesh; + blend_shapes.clear(); +} - PoolVector faces; - faces.resize(facecount); - PoolVector::Write facesw = faces.write(); +void ArrayMesh::set_blend_shape_mode(BlendShapeMode p_mode) { - int widx = 0; + blend_shape_mode = p_mode; + VS::get_singleton()->mesh_set_blend_shape_mode(mesh, (VS::BlendShapeMode)p_mode); +} - for (int i = 0; i < get_surface_count(); i++) { +ArrayMesh::BlendShapeMode ArrayMesh::get_blend_shape_mode() const { - if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) - continue; + return blend_shape_mode; +} - Array a = surface_get_arrays(i); +void ArrayMesh::surface_remove(int p_idx) { - int vc = surface_get_array_len(i); - PoolVector vertices = a[ARRAY_VERTEX]; - PoolVector::Read vr = vertices.read(); + ERR_FAIL_INDEX(p_idx, surfaces.size()); + VisualServer::get_singleton()->mesh_remove_surface(mesh, p_idx); + surfaces.remove(p_idx); - if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { + _clear_triangle_mesh(); + _recompute_aabb(); + _change_notify(); + emit_changed(); +} - int ic = surface_get_array_index_len(i); - PoolVector indices = a[ARRAY_INDEX]; - PoolVector::Read ir = indices.read(); +int ArrayMesh::surface_get_array_len(int p_idx) const { + + ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); + return VisualServer::get_singleton()->mesh_surface_get_array_len(mesh, p_idx); +} - for (int i = 0; i < ic; i++) { - int index = ir[i]; - facesw[widx++] = vr[index]; - } +int ArrayMesh::surface_get_array_index_len(int p_idx) const { - } else { + ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); + return VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, p_idx); +} - for (int i = 0; i < vc; i++) - facesw[widx++] = vr[i]; - } - } +uint32_t ArrayMesh::surface_get_format(int p_idx) const { - facesw = PoolVector::Write(); + ERR_FAIL_INDEX_V(p_idx, surfaces.size(), 0); + return VisualServer::get_singleton()->mesh_surface_get_format(mesh, p_idx); +} - triangle_mesh = Ref(memnew(TriangleMesh)); - triangle_mesh->create(faces); +ArrayMesh::PrimitiveType ArrayMesh::surface_get_primitive_type(int p_idx) const { - return triangle_mesh; + ERR_FAIL_INDEX_V(p_idx, surfaces.size(), PRIMITIVE_LINES); + return (PrimitiveType)VisualServer::get_singleton()->mesh_surface_get_primitive_type(mesh, p_idx); } -Ref Mesh::create_outline(float p_margin) const { +void ArrayMesh::surface_set_material(int p_idx, const Ref &p_material) { - Array arrays; - int index_accum = 0; - for (int i = 0; i < get_surface_count(); i++) { + ERR_FAIL_INDEX(p_idx, surfaces.size()); + if (surfaces[p_idx].material == p_material) + return; + surfaces[p_idx].material = p_material; + VisualServer::get_singleton()->mesh_surface_set_material(mesh, p_idx, p_material.is_null() ? RID() : p_material->get_rid()); - if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) - continue; + _change_notify("material"); +} - Array a = surface_get_arrays(i); - int vcount = 0; +void ArrayMesh::surface_set_name(int p_idx, const String &p_name) { - if (i == 0) { - arrays = a; - PoolVector v = a[ARRAY_VERTEX]; - index_accum += v.size(); - } else { + ERR_FAIL_INDEX(p_idx, surfaces.size()); - for (int j = 0; j < arrays.size(); j++) { + surfaces[p_idx].name = p_name; +} - if (arrays[j].get_type() == Variant::NIL || a[j].get_type() == Variant::NIL) { - //mismatch, do not use - arrays[j] = Variant(); - continue; - } +String ArrayMesh::surface_get_name(int p_idx) const { - switch (j) { + ERR_FAIL_INDEX_V(p_idx, surfaces.size(), String()); + return surfaces[p_idx].name; +} - case ARRAY_VERTEX: - case ARRAY_NORMAL: { +void ArrayMesh::surface_set_custom_aabb(int p_idx, const Rect3 &p_aabb) { - PoolVector dst = arrays[j]; - PoolVector src = a[j]; - if (j == ARRAY_VERTEX) - vcount = src.size(); - if (dst.size() == 0 || src.size() == 0) { - arrays[j] = Variant(); - continue; - } - dst.append_array(src); - arrays[j] = dst; - } break; - case ARRAY_TANGENT: - case ARRAY_BONES: - case ARRAY_WEIGHTS: { + ERR_FAIL_INDEX(p_idx, surfaces.size()); + surfaces[p_idx].aabb = p_aabb; + // set custom aabb too? +} - PoolVector dst = arrays[j]; - PoolVector src = a[j]; - if (dst.size() == 0 || src.size() == 0) { - arrays[j] = Variant(); - continue; - } - dst.append_array(src); - arrays[j] = dst; +Ref ArrayMesh::surface_get_material(int p_idx) const { - } break; - case ARRAY_COLOR: { - PoolVector dst = arrays[j]; - PoolVector src = a[j]; - if (dst.size() == 0 || src.size() == 0) { - arrays[j] = Variant(); - continue; - } - dst.append_array(src); - arrays[j] = dst; + ERR_FAIL_INDEX_V(p_idx, surfaces.size(), Ref()); + return surfaces[p_idx].material; +} - } break; - case ARRAY_TEX_UV: - case ARRAY_TEX_UV2: { - PoolVector dst = arrays[j]; - PoolVector src = a[j]; - if (dst.size() == 0 || src.size() == 0) { - arrays[j] = Variant(); - continue; - } - dst.append_array(src); - arrays[j] = dst; +void ArrayMesh::add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data) { - } break; - case ARRAY_INDEX: { - PoolVector dst = arrays[j]; - PoolVector src = a[j]; - if (dst.size() == 0 || src.size() == 0) { - arrays[j] = Variant(); - continue; - } - { - int ss = src.size(); - PoolVector::Write w = src.write(); - for (int k = 0; k < ss; k++) { - w[k] += index_accum; - } - } - dst.append_array(src); - arrays[j] = dst; - index_accum += vcount; + VisualServer::get_singleton()->mesh_add_surface_from_mesh_data(mesh, p_mesh_data); + Rect3 aabb; + for (int i = 0; i < p_mesh_data.vertices.size(); i++) { - } break; - } - } - } + if (i == 0) + aabb.pos = p_mesh_data.vertices[i]; + else + aabb.expand_to(p_mesh_data.vertices[i]); } - { - PoolVector::Write ir; - PoolVector indices = arrays[ARRAY_INDEX]; - bool has_indices = false; - PoolVector vertices = arrays[ARRAY_VERTEX]; - int vc = vertices.size(); - ERR_FAIL_COND_V(!vc, Ref()); - PoolVector::Write r = vertices.write(); + Surface s; + s.aabb = aabb; + if (surfaces.size() == 0) + aabb = s.aabb; + else + aabb.merge_with(s.aabb); - if (indices.size()) { - vc = indices.size(); - ir = indices.write(); - has_indices = true; - } + _clear_triangle_mesh(); - Map normal_accum; + surfaces.push_back(s); + _change_notify(); - //fill normals with triangle normals - for (int i = 0; i < vc; i += 3) { + emit_changed(); +} - Vector3 t[3]; +RID ArrayMesh::get_rid() const { - if (has_indices) { - t[0] = r[ir[i + 0]]; - t[1] = r[ir[i + 1]]; - t[2] = r[ir[i + 2]]; - } else { - t[0] = r[i + 0]; - t[1] = r[i + 1]; - t[2] = r[i + 2]; - } + return mesh; +} +Rect3 ArrayMesh::get_aabb() const { - Vector3 n = Plane(t[0], t[1], t[2]).normal; + return aabb; +} - for (int j = 0; j < 3; j++) { +void ArrayMesh::set_custom_aabb(const Rect3 &p_custom) { - Map::Element *E = normal_accum.find(t[j]); - if (!E) { - normal_accum[t[j]] = n; - } else { - float d = n.dot(E->get()); - if (d < 1.0) - E->get() += n * (1.0 - d); - //E->get()+=n; - } - } - } + custom_aabb = p_custom; + VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); +} - //normalize +Rect3 ArrayMesh::get_custom_aabb() const { - for (Map::Element *E = normal_accum.front(); E; E = E->next()) { - E->get().normalize(); - } + return custom_aabb; +} - //displace normals - int vc2 = vertices.size(); +void ArrayMesh::center_geometry() { - for (int i = 0; i < vc2; i++) { + /* + Vector3 ofs = aabb.pos+aabb.size*0.5; - Vector3 t = r[i]; + for(int i=0;i::Element *E = normal_accum.find(t); - ERR_CONTINUE(!E); + PoolVector geom = surface_get_array(i,ARRAY_VERTEX); + int gc =geom.size(); + PoolVector::Write w = geom.write(); + surfaces[i].aabb.pos-=ofs; - t += E->get() * p_margin; - r[i] = t; + for(int i=0;i::Write(); - arrays[ARRAY_VERTEX] = vertices; + w = PoolVector::Write(); - if (!has_indices) { + surface_set_array(i,ARRAY_VERTEX,geom); - PoolVector new_indices; - new_indices.resize(vertices.size()); - PoolVector::Write iw = new_indices.write(); + } - for (int j = 0; j < vc2; j += 3) { + aabb.pos-=ofs; - iw[j] = j; - iw[j + 1] = j + 2; - iw[j + 2] = j + 1; - } +*/ +} - iw = PoolVector::Write(); - arrays[ARRAY_INDEX] = new_indices; +void ArrayMesh::regen_normalmaps() { - } else { + Vector > surfs; + for (int i = 0; i < get_surface_count(); i++) { - for (int j = 0; j < vc; j += 3) { + Ref st = memnew(SurfaceTool); + st->create_from(Ref(this), i); + surfs.push_back(st); + } - SWAP(ir[j + 1], ir[j + 2]); - } - ir = PoolVector::Write(); - arrays[ARRAY_INDEX] = indices; - } + while (get_surface_count()) { + surface_remove(0); } - Ref newmesh = memnew(Mesh); - newmesh->add_surface_from_arrays(PRIMITIVE_TRIANGLES, arrays); - return newmesh; + for (int i = 0; i < surfs.size(); i++) { + + surfs[i]->generate_tangents(); + surfs[i]->commit(Ref(this)); + } } -void Mesh::_bind_methods() { - - ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &Mesh::add_blend_shape); - ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &Mesh::get_blend_shape_count); - ClassDB::bind_method(D_METHOD("get_blend_shape_name", "index"), &Mesh::get_blend_shape_name); - ClassDB::bind_method(D_METHOD("clear_blend_shapes"), &Mesh::clear_blend_shapes); - ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &Mesh::set_blend_shape_mode); - ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &Mesh::get_blend_shape_mode); - - ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "compress_flags"), &Mesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT)); - ClassDB::bind_method(D_METHOD("get_surface_count"), &Mesh::get_surface_count); - ClassDB::bind_method(D_METHOD("surface_remove", "surf_idx"), &Mesh::surface_remove); - ClassDB::bind_method(D_METHOD("surface_get_array_len", "surf_idx"), &Mesh::surface_get_array_len); - ClassDB::bind_method(D_METHOD("surface_get_array_index_len", "surf_idx"), &Mesh::surface_get_array_index_len); - ClassDB::bind_method(D_METHOD("surface_get_format", "surf_idx"), &Mesh::surface_get_format); - ClassDB::bind_method(D_METHOD("surface_get_primitive_type", "surf_idx"), &Mesh::surface_get_primitive_type); - ClassDB::bind_method(D_METHOD("surface_set_material", "surf_idx", "material:Material"), &Mesh::surface_set_material); - ClassDB::bind_method(D_METHOD("surface_get_material:Material", "surf_idx"), &Mesh::surface_get_material); - ClassDB::bind_method(D_METHOD("surface_set_name", "surf_idx", "name"), &Mesh::surface_set_name); - ClassDB::bind_method(D_METHOD("surface_get_name", "surf_idx"), &Mesh::surface_get_name); - ClassDB::bind_method(D_METHOD("create_trimesh_shape:Shape"), &Mesh::create_trimesh_shape); - ClassDB::bind_method(D_METHOD("create_convex_shape:Shape"), &Mesh::create_convex_shape); - ClassDB::bind_method(D_METHOD("create_outline:Mesh", "margin"), &Mesh::create_outline); - ClassDB::bind_method(D_METHOD("center_geometry"), &Mesh::center_geometry); +void ArrayMesh::_bind_methods() { + + ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &ArrayMesh::add_blend_shape); + ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &ArrayMesh::get_blend_shape_count); + ClassDB::bind_method(D_METHOD("get_blend_shape_name", "index"), &ArrayMesh::get_blend_shape_name); + ClassDB::bind_method(D_METHOD("clear_blend_shapes"), &ArrayMesh::clear_blend_shapes); + ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &ArrayMesh::set_blend_shape_mode); + ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &ArrayMesh::get_blend_shape_mode); + + ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT)); + ClassDB::bind_method(D_METHOD("get_surface_count"), &ArrayMesh::get_surface_count); + ClassDB::bind_method(D_METHOD("surface_remove", "surf_idx"), &ArrayMesh::surface_remove); + ClassDB::bind_method(D_METHOD("surface_get_array_len", "surf_idx"), &ArrayMesh::surface_get_array_len); + ClassDB::bind_method(D_METHOD("surface_get_array_index_len", "surf_idx"), &ArrayMesh::surface_get_array_index_len); + ClassDB::bind_method(D_METHOD("surface_get_format", "surf_idx"), &ArrayMesh::surface_get_format); + ClassDB::bind_method(D_METHOD("surface_get_primitive_type", "surf_idx"), &ArrayMesh::surface_get_primitive_type); + ClassDB::bind_method(D_METHOD("surface_set_material", "surf_idx", "material:Material"), &ArrayMesh::surface_set_material); + ClassDB::bind_method(D_METHOD("surface_get_material:Material", "surf_idx"), &ArrayMesh::surface_get_material); + ClassDB::bind_method(D_METHOD("surface_set_name", "surf_idx", "name"), &ArrayMesh::surface_set_name); + ClassDB::bind_method(D_METHOD("surface_get_name", "surf_idx"), &ArrayMesh::surface_get_name); + ClassDB::bind_method(D_METHOD("create_trimesh_shape:Shape"), &ArrayMesh::create_trimesh_shape); + ClassDB::bind_method(D_METHOD("create_convex_shape:Shape"), &ArrayMesh::create_convex_shape); + ClassDB::bind_method(D_METHOD("create_outline:ArrayMesh", "margin"), &ArrayMesh::create_outline); + ClassDB::bind_method(D_METHOD("center_geometry"), &ArrayMesh::center_geometry); ClassDB::set_method_flags(get_class_static(), _scs_create("center_geometry"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - ClassDB::bind_method(D_METHOD("regen_normalmaps"), &Mesh::regen_normalmaps); + ClassDB::bind_method(D_METHOD("regen_normalmaps"), &ArrayMesh::regen_normalmaps); ClassDB::set_method_flags(get_class_static(), _scs_create("regen_normalmaps"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - ClassDB::bind_method(D_METHOD("get_faces"), &Mesh::get_faces); - ClassDB::bind_method(D_METHOD("generate_triangle_mesh:TriangleMesh"), &Mesh::generate_triangle_mesh); + ClassDB::bind_method(D_METHOD("get_faces"), &ArrayMesh::get_faces); + ClassDB::bind_method(D_METHOD("generate_triangle_mesh:TriangleMesh"), &ArrayMesh::generate_triangle_mesh); - ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &Mesh::set_custom_aabb); - ClassDB::bind_method(D_METHOD("get_custom_aabb"), &Mesh::get_custom_aabb); + ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &ArrayMesh::set_custom_aabb); + ClassDB::bind_method(D_METHOD("get_custom_aabb"), &ArrayMesh::get_custom_aabb); BIND_CONSTANT(NO_INDEX_ARRAY); BIND_CONSTANT(ARRAY_WEIGHTS_SIZE); @@ -1027,19 +1036,19 @@ void Mesh::_bind_methods() { BIND_CONSTANT(PRIMITIVE_TRIANGLE_FAN); } -Mesh::Mesh() { +ArrayMesh::ArrayMesh() { mesh = VisualServer::get_singleton()->mesh_create(); blend_shape_mode = BLEND_SHAPE_MODE_RELATIVE; } -Mesh::~Mesh() { +ArrayMesh::~ArrayMesh() { VisualServer::get_singleton()->free(mesh); } //////////////////////// - +#if 0 void QuadMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_material", "material:Material"), &QuadMesh::set_material); @@ -1105,3 +1114,4 @@ QuadMesh::QuadMesh() { add_surface_from_arrays(PRIMITIVE_TRIANGLE_FAN, arr); } +#endif diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index e441b4924a..7804a84f81 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -38,10 +38,13 @@ /** @author Juan Linietsky */ -class Mesh : public Resource { +class Mesh : public Resource { GDCLASS(Mesh, Resource); - RES_BASE_EXTENSION("msh"); + + mutable Ref triangle_mesh; //cached +protected: + void _clear_triangle_mesh(); public: enum { @@ -111,6 +114,34 @@ public: BLEND_SHAPE_MODE_RELATIVE = VS::BLEND_SHAPE_MODE_RELATIVE, }; + virtual int get_surface_count() const = 0; + virtual int surface_get_array_len(int p_idx) const = 0; + virtual int surface_get_array_index_len(int p_idx) const = 0; + virtual Array surface_get_arrays(int p_surface) const = 0; + virtual uint32_t surface_get_format(int p_idx) const = 0; + virtual PrimitiveType surface_get_primitive_type(int p_idx) const = 0; + virtual Ref surface_get_material(int p_idx) const = 0; + virtual int get_blend_shape_count() const = 0; + virtual StringName get_blend_shape_name(int p_index) const = 0; + + PoolVector get_faces() const; + Ref generate_triangle_mesh() const; + + Ref create_trimesh_shape() const; + Ref create_convex_shape() const; + + Ref create_outline(float p_margin) const; + + virtual Rect3 get_aabb() const = 0; + + Mesh(); +}; + +class ArrayMesh : public Mesh { + + GDCLASS(ArrayMesh, Mesh); + RES_BASE_EXTENSION("msh"); + private: struct Surface { String name; @@ -124,8 +155,6 @@ private: Vector blend_shapes; Rect3 custom_aabb; - mutable Ref triangle_mesh; - void _recompute_aabb(); protected: @@ -177,21 +206,15 @@ public: Rect3 get_aabb() const; virtual RID get_rid() const; - Ref create_trimesh_shape() const; - Ref create_convex_shape() const; - - Ref create_outline(float p_margin) const; - void center_geometry(); void regen_normalmaps(); - PoolVector get_faces() const; - Ref generate_triangle_mesh() const; - Mesh(); + ArrayMesh(); - ~Mesh(); + ~ArrayMesh(); }; +#if 0 class QuadMesh : public Mesh { GDCLASS(QuadMesh, Mesh) @@ -206,6 +229,8 @@ public: QuadMesh(); }; +#endif + VARIANT_ENUM_CAST(Mesh::ArrayType); VARIANT_ENUM_CAST(Mesh::PrimitiveType); VARIANT_ENUM_CAST(Mesh::BlendShapeMode); diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp index b6b47bf443..dc3713fb57 100644 --- a/scene/resources/mesh_data_tool.cpp +++ b/scene/resources/mesh_data_tool.cpp @@ -38,7 +38,7 @@ void MeshDataTool::clear() { format = 0; } -Error MeshDataTool::create_from_surface(const Ref &p_mesh, int p_surface) { +Error MeshDataTool::create_from_surface(const Ref &p_mesh, int p_surface) { ERR_FAIL_COND_V(p_mesh.is_null(), ERR_INVALID_PARAMETER); @@ -179,7 +179,7 @@ Error MeshDataTool::create_from_surface(const Ref &p_mesh, int p_surface) return OK; } -Error MeshDataTool::commit_to_surface(const Ref &p_mesh) { +Error MeshDataTool::commit_to_surface(const Ref &p_mesh) { ERR_FAIL_COND_V(p_mesh.is_null(), ERR_INVALID_PARAMETER); Array arr; @@ -309,7 +309,7 @@ Error MeshDataTool::commit_to_surface(const Ref &p_mesh) { if (w.size()) arr[Mesh::ARRAY_WEIGHTS] = w; - Ref ncmesh = p_mesh; + Ref ncmesh = p_mesh; int sc = ncmesh->get_surface_count(); ncmesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arr); ncmesh->surface_set_material(sc, material); diff --git a/scene/resources/mesh_data_tool.h b/scene/resources/mesh_data_tool.h index f6797d3e5e..ad771edbd1 100644 --- a/scene/resources/mesh_data_tool.h +++ b/scene/resources/mesh_data_tool.h @@ -78,8 +78,8 @@ protected: public: void clear(); - Error create_from_surface(const Ref &p_mesh, int p_surface); - Error commit_to_surface(const Ref &p_mesh); + Error create_from_surface(const Ref &p_mesh, int p_surface); + Error commit_to_surface(const Ref &p_mesh); int get_format() const; diff --git a/scene/resources/shape.cpp b/scene/resources/shape.cpp index b449932b17..77f2096d9b 100644 --- a/scene/resources/shape.cpp +++ b/scene/resources/shape.cpp @@ -49,14 +49,14 @@ void Shape::add_vertices_to_array(PoolVector &array, const Transform &p } } -Ref Shape::get_debug_mesh() { +Ref Shape::get_debug_mesh() { if (debug_mesh_cache.is_valid()) return debug_mesh_cache; Vector lines = _gen_debug_mesh_lines(); - debug_mesh_cache = Ref(memnew(Mesh)); + debug_mesh_cache = Ref(memnew(ArrayMesh)); if (!lines.empty()) { //make mesh diff --git a/scene/resources/shape.h b/scene/resources/shape.h index 01b8db650e..ea3ba9ab0a 100644 --- a/scene/resources/shape.h +++ b/scene/resources/shape.h @@ -31,7 +31,7 @@ #define SHAPE_H #include "resource.h" -class Mesh; +class ArrayMesh; class Shape : public Resource { @@ -40,7 +40,7 @@ class Shape : public Resource { RES_BASE_EXTENSION("shp"); RID shape; - Ref debug_mesh_cache; + Ref debug_mesh_cache; protected: _FORCE_INLINE_ RID get_shape() const { return shape; } @@ -50,7 +50,7 @@ protected: public: virtual RID get_rid() const { return shape; } - Ref get_debug_mesh(); + Ref get_debug_mesh(); void add_vertices_to_array(PoolVector &array, const Transform &p_xform); diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 4c36d79a7a..60fb97c792 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -224,13 +224,13 @@ void SurfaceTool::add_index(int p_index) { index_array.push_back(p_index); } -Ref SurfaceTool::commit(const Ref &p_existing) { +Ref SurfaceTool::commit(const Ref &p_existing) { - Ref mesh; + Ref mesh; if (p_existing.is_valid()) mesh = p_existing; else - mesh = Ref(memnew(Mesh)); + mesh.instance(); int varr_len = vertex_array.size(); diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index b143086e11..753c3626b8 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -125,7 +125,7 @@ public: void create_from(const Ref &p_existing, int p_surface); void append_from(const Ref &p_existing, int p_surface, const Transform &p_xform); - Ref commit(const Ref &p_existing = Ref()); + Ref commit(const Ref &p_existing = Ref()); SurfaceTool(); }; diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index 44ec13af45..e0201420fe 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -105,6 +105,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SPECIAL"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["DISCARD"] = ShaderLanguage::TYPE_BOOL; shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["POINT_COORD"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SIDE"] = ShaderLanguage::TYPE_FLOAT; -- cgit v1.2.3