| 1 | /**************************************************************************/ | 
|---|
| 2 | /*  mesh.cpp                                                              */ | 
|---|
| 3 | /**************************************************************************/ | 
|---|
| 4 | /*                         This file is part of:                          */ | 
|---|
| 5 | /*                             GODOT ENGINE                               */ | 
|---|
| 6 | /*                        https://godotengine.org                         */ | 
|---|
| 7 | /**************************************************************************/ | 
|---|
| 8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ | 
|---|
| 9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */ | 
|---|
| 10 | /*                                                                        */ | 
|---|
| 11 | /* Permission is hereby granted, free of charge, to any person obtaining  */ | 
|---|
| 12 | /* a copy of this software and associated documentation files (the        */ | 
|---|
| 13 | /* "Software"), to deal in the Software without restriction, including    */ | 
|---|
| 14 | /* without limitation the rights to use, copy, modify, merge, publish,    */ | 
|---|
| 15 | /* distribute, sublicense, and/or sell copies of the Software, and to     */ | 
|---|
| 16 | /* permit persons to whom the Software is furnished to do so, subject to  */ | 
|---|
| 17 | /* the following conditions:                                              */ | 
|---|
| 18 | /*                                                                        */ | 
|---|
| 19 | /* The above copyright notice and this permission notice shall be         */ | 
|---|
| 20 | /* included in all copies or substantial portions of the Software.        */ | 
|---|
| 21 | /*                                                                        */ | 
|---|
| 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */ | 
|---|
| 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */ | 
|---|
| 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ | 
|---|
| 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */ | 
|---|
| 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */ | 
|---|
| 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */ | 
|---|
| 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */ | 
|---|
| 29 | /**************************************************************************/ | 
|---|
| 30 |  | 
|---|
| 31 | #include "mesh.h" | 
|---|
| 32 |  | 
|---|
| 33 | #include "core/math/convex_hull.h" | 
|---|
| 34 | #include "core/templates/pair.h" | 
|---|
| 35 | #include "scene/resources/surface_tool.h" | 
|---|
| 36 |  | 
|---|
| 37 | #include "scene/resources/concave_polygon_shape_3d.h" | 
|---|
| 38 | #include "scene/resources/convex_polygon_shape_3d.h" | 
|---|
| 39 |  | 
|---|
| 40 | void MeshConvexDecompositionSettings::set_max_concavity(real_t p_max_concavity) { | 
|---|
| 41 | max_concavity = CLAMP(p_max_concavity, 0.001, 1.0); | 
|---|
| 42 | } | 
|---|
| 43 |  | 
|---|
| 44 | real_t MeshConvexDecompositionSettings::get_max_concavity() const { | 
|---|
| 45 | return max_concavity; | 
|---|
| 46 | }; | 
|---|
| 47 |  | 
|---|
| 48 | void MeshConvexDecompositionSettings::set_symmetry_planes_clipping_bias(real_t p_symmetry_planes_clipping_bias) { | 
|---|
| 49 | symmetry_planes_clipping_bias = CLAMP(p_symmetry_planes_clipping_bias, 0.0, 1.0); | 
|---|
| 50 | }; | 
|---|
| 51 |  | 
|---|
| 52 | real_t MeshConvexDecompositionSettings::get_symmetry_planes_clipping_bias() const { | 
|---|
| 53 | return symmetry_planes_clipping_bias; | 
|---|
| 54 | }; | 
|---|
| 55 |  | 
|---|
| 56 | void MeshConvexDecompositionSettings::set_revolution_axes_clipping_bias(real_t p_revolution_axes_clipping_bias) { | 
|---|
| 57 | revolution_axes_clipping_bias = CLAMP(p_revolution_axes_clipping_bias, 0.0, 1.0); | 
|---|
| 58 | }; | 
|---|
| 59 |  | 
|---|
| 60 | real_t MeshConvexDecompositionSettings::get_revolution_axes_clipping_bias() const { | 
|---|
| 61 | return revolution_axes_clipping_bias; | 
|---|
| 62 | }; | 
|---|
| 63 |  | 
|---|
| 64 | void MeshConvexDecompositionSettings::set_min_volume_per_convex_hull(real_t p_min_volume_per_convex_hull) { | 
|---|
| 65 | min_volume_per_convex_hull = CLAMP(p_min_volume_per_convex_hull, 0.0001, 0.01); | 
|---|
| 66 | } | 
|---|
| 67 |  | 
|---|
| 68 | real_t MeshConvexDecompositionSettings::get_min_volume_per_convex_hull() const { | 
|---|
| 69 | return min_volume_per_convex_hull; | 
|---|
| 70 | } | 
|---|
| 71 |  | 
|---|
| 72 | void MeshConvexDecompositionSettings::set_resolution(uint32_t p_resolution) { | 
|---|
| 73 | resolution = p_resolution < 10'000 ? 10'000 : (p_resolution > 100'000 ? 100'000 : p_resolution); | 
|---|
| 74 | } | 
|---|
| 75 |  | 
|---|
| 76 | uint32_t MeshConvexDecompositionSettings::get_resolution() const { | 
|---|
| 77 | return resolution; | 
|---|
| 78 | } | 
|---|
| 79 |  | 
|---|
| 80 | void MeshConvexDecompositionSettings::set_max_num_vertices_per_convex_hull(uint32_t p_max_num_vertices_per_convex_hull) { | 
|---|
| 81 | max_num_vertices_per_convex_hull = p_max_num_vertices_per_convex_hull < 4 ? 4 : (p_max_num_vertices_per_convex_hull > 1024 ? 1024 : p_max_num_vertices_per_convex_hull); | 
|---|
| 82 | } | 
|---|
| 83 |  | 
|---|
| 84 | uint32_t MeshConvexDecompositionSettings::get_max_num_vertices_per_convex_hull() const { | 
|---|
| 85 | return max_num_vertices_per_convex_hull; | 
|---|
| 86 | } | 
|---|
| 87 |  | 
|---|
| 88 | void MeshConvexDecompositionSettings::set_plane_downsampling(uint32_t p_plane_downsampling) { | 
|---|
| 89 | plane_downsampling = p_plane_downsampling < 1 ? 1 : (p_plane_downsampling > 16 ? 16 : p_plane_downsampling); | 
|---|
| 90 | } | 
|---|
| 91 |  | 
|---|
| 92 | uint32_t MeshConvexDecompositionSettings::get_plane_downsampling() const { | 
|---|
| 93 | return plane_downsampling; | 
|---|
| 94 | } | 
|---|
| 95 |  | 
|---|
| 96 | void MeshConvexDecompositionSettings::set_convex_hull_downsampling(uint32_t p_convex_hull_downsampling) { | 
|---|
| 97 | convex_hull_downsampling = p_convex_hull_downsampling < 1 ? 1 : (p_convex_hull_downsampling > 16 ? 16 : p_convex_hull_downsampling); | 
|---|
| 98 | } | 
|---|
| 99 |  | 
|---|
| 100 | uint32_t MeshConvexDecompositionSettings::get_convex_hull_downsampling() const { | 
|---|
| 101 | return convex_hull_downsampling; | 
|---|
| 102 | } | 
|---|
| 103 |  | 
|---|
| 104 | void MeshConvexDecompositionSettings::set_normalize_mesh(bool p_normalize_mesh) { | 
|---|
| 105 | normalize_mesh = p_normalize_mesh; | 
|---|
| 106 | } | 
|---|
| 107 |  | 
|---|
| 108 | bool MeshConvexDecompositionSettings::get_normalize_mesh() const { | 
|---|
| 109 | return normalize_mesh; | 
|---|
| 110 | } | 
|---|
| 111 |  | 
|---|
| 112 | void MeshConvexDecompositionSettings::set_mode(Mode p_mode) { | 
|---|
| 113 | mode = p_mode; | 
|---|
| 114 | } | 
|---|
| 115 |  | 
|---|
| 116 | MeshConvexDecompositionSettings::Mode MeshConvexDecompositionSettings::get_mode() const { | 
|---|
| 117 | return mode; | 
|---|
| 118 | } | 
|---|
| 119 |  | 
|---|
| 120 | void MeshConvexDecompositionSettings::set_convex_hull_approximation(bool p_convex_hull_approximation) { | 
|---|
| 121 | convex_hull_approximation = p_convex_hull_approximation; | 
|---|
| 122 | } | 
|---|
| 123 |  | 
|---|
| 124 | bool MeshConvexDecompositionSettings::get_convex_hull_approximation() const { | 
|---|
| 125 | return convex_hull_approximation; | 
|---|
| 126 | } | 
|---|
| 127 |  | 
|---|
| 128 | void MeshConvexDecompositionSettings::set_max_convex_hulls(uint32_t p_max_convex_hulls) { | 
|---|
| 129 | max_convex_hulls = p_max_convex_hulls < 1 ? 1 : (p_max_convex_hulls > 32 ? 32 : p_max_convex_hulls); | 
|---|
| 130 | } | 
|---|
| 131 |  | 
|---|
| 132 | uint32_t MeshConvexDecompositionSettings::get_max_convex_hulls() const { | 
|---|
| 133 | return max_convex_hulls; | 
|---|
| 134 | } | 
|---|
| 135 |  | 
|---|
| 136 | void MeshConvexDecompositionSettings::set_project_hull_vertices(bool p_project_hull_vertices) { | 
|---|
| 137 | project_hull_vertices = p_project_hull_vertices; | 
|---|
| 138 | } | 
|---|
| 139 |  | 
|---|
| 140 | bool MeshConvexDecompositionSettings::get_project_hull_vertices() const { | 
|---|
| 141 | return project_hull_vertices; | 
|---|
| 142 | } | 
|---|
| 143 |  | 
|---|
| 144 | void MeshConvexDecompositionSettings::_bind_methods() { | 
|---|
| 145 | ClassDB::bind_method(D_METHOD( "set_max_concavity", "max_concavity"), &MeshConvexDecompositionSettings::set_max_concavity); | 
|---|
| 146 | ClassDB::bind_method(D_METHOD( "get_max_concavity"), &MeshConvexDecompositionSettings::get_max_concavity); | 
|---|
| 147 |  | 
|---|
| 148 | ClassDB::bind_method(D_METHOD( "set_symmetry_planes_clipping_bias", "symmetry_planes_clipping_bias"), &MeshConvexDecompositionSettings::set_symmetry_planes_clipping_bias); | 
|---|
| 149 | ClassDB::bind_method(D_METHOD( "get_symmetry_planes_clipping_bias"), &MeshConvexDecompositionSettings::get_symmetry_planes_clipping_bias); | 
|---|
| 150 |  | 
|---|
| 151 | ClassDB::bind_method(D_METHOD( "set_revolution_axes_clipping_bias", "revolution_axes_clipping_bias"), &MeshConvexDecompositionSettings::set_revolution_axes_clipping_bias); | 
|---|
| 152 | ClassDB::bind_method(D_METHOD( "get_revolution_axes_clipping_bias"), &MeshConvexDecompositionSettings::get_revolution_axes_clipping_bias); | 
|---|
| 153 |  | 
|---|
| 154 | ClassDB::bind_method(D_METHOD( "set_min_volume_per_convex_hull", "min_volume_per_convex_hull"), &MeshConvexDecompositionSettings::set_min_volume_per_convex_hull); | 
|---|
| 155 | ClassDB::bind_method(D_METHOD( "get_min_volume_per_convex_hull"), &MeshConvexDecompositionSettings::get_min_volume_per_convex_hull); | 
|---|
| 156 |  | 
|---|
| 157 | ClassDB::bind_method(D_METHOD( "set_resolution", "min_volume_per_convex_hull"), &MeshConvexDecompositionSettings::set_resolution); | 
|---|
| 158 | ClassDB::bind_method(D_METHOD( "get_resolution"), &MeshConvexDecompositionSettings::get_resolution); | 
|---|
| 159 |  | 
|---|
| 160 | ClassDB::bind_method(D_METHOD( "set_max_num_vertices_per_convex_hull", "max_num_vertices_per_convex_hull"), &MeshConvexDecompositionSettings::set_max_num_vertices_per_convex_hull); | 
|---|
| 161 | ClassDB::bind_method(D_METHOD( "get_max_num_vertices_per_convex_hull"), &MeshConvexDecompositionSettings::get_max_num_vertices_per_convex_hull); | 
|---|
| 162 |  | 
|---|
| 163 | ClassDB::bind_method(D_METHOD( "set_plane_downsampling", "plane_downsampling"), &MeshConvexDecompositionSettings::set_plane_downsampling); | 
|---|
| 164 | ClassDB::bind_method(D_METHOD( "get_plane_downsampling"), &MeshConvexDecompositionSettings::get_plane_downsampling); | 
|---|
| 165 |  | 
|---|
| 166 | ClassDB::bind_method(D_METHOD( "set_convex_hull_downsampling", "convex_hull_downsampling"), &MeshConvexDecompositionSettings::set_convex_hull_downsampling); | 
|---|
| 167 | ClassDB::bind_method(D_METHOD( "get_convex_hull_downsampling"), &MeshConvexDecompositionSettings::get_convex_hull_downsampling); | 
|---|
| 168 |  | 
|---|
| 169 | ClassDB::bind_method(D_METHOD( "set_normalize_mesh", "normalize_mesh"), &MeshConvexDecompositionSettings::set_normalize_mesh); | 
|---|
| 170 | ClassDB::bind_method(D_METHOD( "get_normalize_mesh"), &MeshConvexDecompositionSettings::get_normalize_mesh); | 
|---|
| 171 |  | 
|---|
| 172 | ClassDB::bind_method(D_METHOD( "set_mode", "mode"), &MeshConvexDecompositionSettings::set_mode); | 
|---|
| 173 | ClassDB::bind_method(D_METHOD( "get_mode"), &MeshConvexDecompositionSettings::get_mode); | 
|---|
| 174 |  | 
|---|
| 175 | ClassDB::bind_method(D_METHOD( "set_convex_hull_approximation", "convex_hull_approximation"), &MeshConvexDecompositionSettings::set_convex_hull_approximation); | 
|---|
| 176 | ClassDB::bind_method(D_METHOD( "get_convex_hull_approximation"), &MeshConvexDecompositionSettings::get_convex_hull_approximation); | 
|---|
| 177 |  | 
|---|
| 178 | ClassDB::bind_method(D_METHOD( "set_max_convex_hulls", "max_convex_hulls"), &MeshConvexDecompositionSettings::set_max_convex_hulls); | 
|---|
| 179 | ClassDB::bind_method(D_METHOD( "get_max_convex_hulls"), &MeshConvexDecompositionSettings::get_max_convex_hulls); | 
|---|
| 180 |  | 
|---|
| 181 | ClassDB::bind_method(D_METHOD( "set_project_hull_vertices", "project_hull_vertices"), &MeshConvexDecompositionSettings::set_project_hull_vertices); | 
|---|
| 182 | ClassDB::bind_method(D_METHOD( "get_project_hull_vertices"), &MeshConvexDecompositionSettings::get_project_hull_vertices); | 
|---|
| 183 |  | 
|---|
| 184 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_concavity", PROPERTY_HINT_RANGE, "0.001,1.0,0.001"), "set_max_concavity", "get_max_concavity"); | 
|---|
| 185 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "symmetry_planes_clipping_bias", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_symmetry_planes_clipping_bias", "get_symmetry_planes_clipping_bias"); | 
|---|
| 186 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "revolution_axes_clipping_bias", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_revolution_axes_clipping_bias", "get_revolution_axes_clipping_bias"); | 
|---|
| 187 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min_volume_per_convex_hull", PROPERTY_HINT_RANGE, "0.0001,0.01,0.0001"), "set_min_volume_per_convex_hull", "get_min_volume_per_convex_hull"); | 
|---|
| 188 | ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution"), "set_resolution", "get_resolution"); | 
|---|
| 189 | ADD_PROPERTY(PropertyInfo(Variant::INT, "max_num_vertices_per_convex_hull"), "set_max_num_vertices_per_convex_hull", "get_max_num_vertices_per_convex_hull"); | 
|---|
| 190 | ADD_PROPERTY(PropertyInfo(Variant::INT, "plane_downsampling", PROPERTY_HINT_RANGE, "1,16,1"), "set_plane_downsampling", "get_plane_downsampling"); | 
|---|
| 191 | ADD_PROPERTY(PropertyInfo(Variant::INT, "convex_hull_downsampling", PROPERTY_HINT_RANGE, "1,16,1"), "set_convex_hull_downsampling", "get_convex_hull_downsampling"); | 
|---|
| 192 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "normalize_mesh"), "set_normalize_mesh", "get_normalize_mesh"); | 
|---|
| 193 | ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Voxel,Tetrahedron"), "set_mode", "get_mode"); | 
|---|
| 194 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "convex_hull_approximation"), "set_convex_hull_approximation", "get_convex_hull_approximation"); | 
|---|
| 195 | ADD_PROPERTY(PropertyInfo(Variant::INT, "max_convex_hulls"), "set_max_convex_hulls", "get_max_convex_hulls"); | 
|---|
| 196 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "project_hull_vertices"), "set_project_hull_vertices", "get_project_hull_vertices"); | 
|---|
| 197 |  | 
|---|
| 198 | BIND_ENUM_CONSTANT(CONVEX_DECOMPOSITION_MODE_VOXEL); | 
|---|
| 199 | BIND_ENUM_CONSTANT(CONVEX_DECOMPOSITION_MODE_TETRAHEDRON); | 
|---|
| 200 | } | 
|---|
| 201 |  | 
|---|
| 202 | Mesh::ConvexDecompositionFunc Mesh::convex_decomposition_function = nullptr; | 
|---|
| 203 |  | 
|---|
| 204 | int Mesh::get_surface_count() const { | 
|---|
| 205 | int ret = 0; | 
|---|
| 206 | GDVIRTUAL_REQUIRED_CALL(_get_surface_count, ret); | 
|---|
| 207 | return ret; | 
|---|
| 208 | } | 
|---|
| 209 |  | 
|---|
| 210 | int Mesh::surface_get_array_len(int p_idx) const { | 
|---|
| 211 | int ret = 0; | 
|---|
| 212 | GDVIRTUAL_REQUIRED_CALL(_surface_get_array_len, p_idx, ret); | 
|---|
| 213 | return ret; | 
|---|
| 214 | } | 
|---|
| 215 |  | 
|---|
| 216 | int Mesh::surface_get_array_index_len(int p_idx) const { | 
|---|
| 217 | int ret = 0; | 
|---|
| 218 | GDVIRTUAL_REQUIRED_CALL(_surface_get_array_index_len, p_idx, ret); | 
|---|
| 219 | return ret; | 
|---|
| 220 | } | 
|---|
| 221 |  | 
|---|
| 222 | Array Mesh::surface_get_arrays(int p_surface) const { | 
|---|
| 223 | Array ret; | 
|---|
| 224 | GDVIRTUAL_REQUIRED_CALL(_surface_get_arrays, p_surface, ret); | 
|---|
| 225 | return ret; | 
|---|
| 226 | } | 
|---|
| 227 |  | 
|---|
| 228 | TypedArray<Array> Mesh::surface_get_blend_shape_arrays(int p_surface) const { | 
|---|
| 229 | TypedArray<Array> ret; | 
|---|
| 230 | GDVIRTUAL_REQUIRED_CALL(_surface_get_blend_shape_arrays, p_surface, ret); | 
|---|
| 231 | return ret; | 
|---|
| 232 | } | 
|---|
| 233 |  | 
|---|
| 234 | Dictionary Mesh::surface_get_lods(int p_surface) const { | 
|---|
| 235 | Dictionary ret; | 
|---|
| 236 | GDVIRTUAL_REQUIRED_CALL(_surface_get_lods, p_surface, ret); | 
|---|
| 237 | return ret; | 
|---|
| 238 | } | 
|---|
| 239 |  | 
|---|
| 240 | BitField<Mesh::ArrayFormat> Mesh::surface_get_format(int p_idx) const { | 
|---|
| 241 | uint32_t ret = 0; | 
|---|
| 242 | GDVIRTUAL_REQUIRED_CALL(_surface_get_format, p_idx, ret); | 
|---|
| 243 | return ret; | 
|---|
| 244 | } | 
|---|
| 245 |  | 
|---|
| 246 | Mesh::PrimitiveType Mesh::surface_get_primitive_type(int p_idx) const { | 
|---|
| 247 | uint32_t ret = PRIMITIVE_MAX; | 
|---|
| 248 | GDVIRTUAL_REQUIRED_CALL(_surface_get_primitive_type, p_idx, ret); | 
|---|
| 249 | return (Mesh::PrimitiveType)ret; | 
|---|
| 250 | } | 
|---|
| 251 |  | 
|---|
| 252 | void Mesh::surface_set_material(int p_idx, const Ref<Material> &p_material) { | 
|---|
| 253 | GDVIRTUAL_REQUIRED_CALL(_surface_set_material, p_idx, p_material); | 
|---|
| 254 | } | 
|---|
| 255 |  | 
|---|
| 256 | Ref<Material> Mesh::surface_get_material(int p_idx) const { | 
|---|
| 257 | Ref<Material> ret; | 
|---|
| 258 | GDVIRTUAL_REQUIRED_CALL(_surface_get_material, p_idx, ret); | 
|---|
| 259 | return ret; | 
|---|
| 260 | } | 
|---|
| 261 |  | 
|---|
| 262 | int Mesh::get_blend_shape_count() const { | 
|---|
| 263 | int ret = 0; | 
|---|
| 264 | GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_count, ret); | 
|---|
| 265 | return ret; | 
|---|
| 266 | } | 
|---|
| 267 |  | 
|---|
| 268 | StringName Mesh::get_blend_shape_name(int p_index) const { | 
|---|
| 269 | StringName ret; | 
|---|
| 270 | GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_name, p_index, ret); | 
|---|
| 271 | return ret; | 
|---|
| 272 | } | 
|---|
| 273 |  | 
|---|
| 274 | void Mesh::set_blend_shape_name(int p_index, const StringName &p_name) { | 
|---|
| 275 | GDVIRTUAL_REQUIRED_CALL(_set_blend_shape_name, p_index, p_name); | 
|---|
| 276 | } | 
|---|
| 277 |  | 
|---|
| 278 | AABB Mesh::get_aabb() const { | 
|---|
| 279 | AABB ret; | 
|---|
| 280 | GDVIRTUAL_REQUIRED_CALL(_get_aabb, ret); | 
|---|
| 281 | return ret; | 
|---|
| 282 | } | 
|---|
| 283 |  | 
|---|
| 284 | Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { | 
|---|
| 285 | if (triangle_mesh.is_valid()) { | 
|---|
| 286 | return triangle_mesh; | 
|---|
| 287 | } | 
|---|
| 288 |  | 
|---|
| 289 | int faces_size = 0; | 
|---|
| 290 |  | 
|---|
| 291 | for (int i = 0; i < get_surface_count(); i++) { | 
|---|
| 292 | switch (surface_get_primitive_type(i)) { | 
|---|
| 293 | case PRIMITIVE_TRIANGLES: { | 
|---|
| 294 | int len = (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? surface_get_array_index_len(i) : surface_get_array_len(i); | 
|---|
| 295 | // Don't error if zero, it's valid (we'll just skip it later). | 
|---|
| 296 | ERR_CONTINUE_MSG((len % 3) != 0, vformat( "Ignoring surface %d, incorrect %s count: %d (for PRIMITIVE_TRIANGLES).", i, (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? "index": "vertex", len)); | 
|---|
| 297 | faces_size += len; | 
|---|
| 298 | } break; | 
|---|
| 299 | case PRIMITIVE_TRIANGLE_STRIP: { | 
|---|
| 300 | int len = (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? surface_get_array_index_len(i) : surface_get_array_len(i); | 
|---|
| 301 | // Don't error if zero, it's valid (we'll just skip it later). | 
|---|
| 302 | ERR_CONTINUE_MSG(len != 0 && len < 3, vformat( "Ignoring surface %d, incorrect %s count: %d (for PRIMITIVE_TRIANGLE_STRIP).", i, (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? "index": "vertex", len)); | 
|---|
| 303 | faces_size += (len == 0) ? 0 : (len - 2) * 3; | 
|---|
| 304 | } break; | 
|---|
| 305 | default: { | 
|---|
| 306 | } break; | 
|---|
| 307 | } | 
|---|
| 308 | } | 
|---|
| 309 |  | 
|---|
| 310 | if (faces_size == 0) { | 
|---|
| 311 | return triangle_mesh; | 
|---|
| 312 | } | 
|---|
| 313 |  | 
|---|
| 314 | Vector<Vector3> faces; | 
|---|
| 315 | faces.resize(faces_size); | 
|---|
| 316 | Vector<int32_t> surface_indices; | 
|---|
| 317 | surface_indices.resize(faces_size / 3); | 
|---|
| 318 | Vector3 *facesw = faces.ptrw(); | 
|---|
| 319 | int32_t *surface_indicesw = surface_indices.ptrw(); | 
|---|
| 320 |  | 
|---|
| 321 | int widx = 0; | 
|---|
| 322 |  | 
|---|
| 323 | for (int i = 0; i < get_surface_count(); i++) { | 
|---|
| 324 | Mesh::PrimitiveType primitive = surface_get_primitive_type(i); | 
|---|
| 325 | if (primitive != PRIMITIVE_TRIANGLES && primitive != PRIMITIVE_TRIANGLE_STRIP) { | 
|---|
| 326 | continue; | 
|---|
| 327 | } | 
|---|
| 328 | int len = (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? surface_get_array_index_len(i) : surface_get_array_len(i); | 
|---|
| 329 | if ((primitive == PRIMITIVE_TRIANGLES && (len == 0 || (len % 3) != 0)) || | 
|---|
| 330 | (primitive == PRIMITIVE_TRIANGLE_STRIP && len < 3) || | 
|---|
| 331 | (surface_get_format(i) & ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY)) { | 
|---|
| 332 | // Error was already shown, just skip (including zero). | 
|---|
| 333 | continue; | 
|---|
| 334 | } | 
|---|
| 335 |  | 
|---|
| 336 | Array a = surface_get_arrays(i); | 
|---|
| 337 | ERR_FAIL_COND_V(a.is_empty(), Ref<TriangleMesh>()); | 
|---|
| 338 |  | 
|---|
| 339 | int vc = surface_get_array_len(i); | 
|---|
| 340 | Vector<Vector3> vertices = a[ARRAY_VERTEX]; | 
|---|
| 341 | ERR_FAIL_COND_V(vertices.is_empty(), Ref<TriangleMesh>()); | 
|---|
| 342 | const Vector3 *vr = vertices.ptr(); | 
|---|
| 343 |  | 
|---|
| 344 | int32_t from_index = widx / 3; | 
|---|
| 345 |  | 
|---|
| 346 | if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { | 
|---|
| 347 | int ic = surface_get_array_index_len(i); | 
|---|
| 348 | Vector<int> indices = a[ARRAY_INDEX]; | 
|---|
| 349 | const int *ir = indices.ptr(); | 
|---|
| 350 |  | 
|---|
| 351 | if (primitive == PRIMITIVE_TRIANGLES) { | 
|---|
| 352 | for (int j = 0; j < ic; j++) { | 
|---|
| 353 | int index = ir[j]; | 
|---|
| 354 | ERR_FAIL_COND_V(index >= vc, Ref<TriangleMesh>()); | 
|---|
| 355 | facesw[widx++] = vr[index]; | 
|---|
| 356 | } | 
|---|
| 357 | } else { // PRIMITIVE_TRIANGLE_STRIP | 
|---|
| 358 | for (int j = 2; j < ic; j++) { | 
|---|
| 359 | facesw[widx++] = vr[ir[j - 2]]; | 
|---|
| 360 | facesw[widx++] = vr[ir[j - 1]]; | 
|---|
| 361 | facesw[widx++] = vr[ir[j]]; | 
|---|
| 362 | } | 
|---|
| 363 | } | 
|---|
| 364 |  | 
|---|
| 365 | } else { | 
|---|
| 366 | if (primitive == PRIMITIVE_TRIANGLES) { | 
|---|
| 367 | for (int j = 0; j < vc; j++) { | 
|---|
| 368 | facesw[widx++] = vr[j]; | 
|---|
| 369 | } | 
|---|
| 370 | } else { // PRIMITIVE_TRIANGLE_STRIP | 
|---|
| 371 | for (int j = 2; j < vc; j++) { | 
|---|
| 372 | facesw[widx++] = vr[j - 2]; | 
|---|
| 373 | facesw[widx++] = vr[j - 1]; | 
|---|
| 374 | facesw[widx++] = vr[j]; | 
|---|
| 375 | } | 
|---|
| 376 | } | 
|---|
| 377 | } | 
|---|
| 378 |  | 
|---|
| 379 | int32_t to_index = widx / 3; | 
|---|
| 380 |  | 
|---|
| 381 | for (int j = from_index; j < to_index; j++) { | 
|---|
| 382 | surface_indicesw[j] = i; | 
|---|
| 383 | } | 
|---|
| 384 | } | 
|---|
| 385 |  | 
|---|
| 386 | triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); | 
|---|
| 387 | triangle_mesh->create(faces); | 
|---|
| 388 |  | 
|---|
| 389 | return triangle_mesh; | 
|---|
| 390 | } | 
|---|
| 391 |  | 
|---|
| 392 | Ref<TriangleMesh> Mesh::generate_surface_triangle_mesh(int p_surface) const { | 
|---|
| 393 | ERR_FAIL_INDEX_V(p_surface, get_surface_count(), Ref<TriangleMesh>()); | 
|---|
| 394 |  | 
|---|
| 395 | if (surface_triangle_meshes.size() != get_surface_count()) { | 
|---|
| 396 | surface_triangle_meshes.resize(get_surface_count()); | 
|---|
| 397 | } | 
|---|
| 398 |  | 
|---|
| 399 | if (surface_triangle_meshes[p_surface].is_valid()) { | 
|---|
| 400 | return surface_triangle_meshes[p_surface]; | 
|---|
| 401 | } | 
|---|
| 402 |  | 
|---|
| 403 | int facecount = 0; | 
|---|
| 404 |  | 
|---|
| 405 | if (surface_get_primitive_type(p_surface) != PRIMITIVE_TRIANGLES) { | 
|---|
| 406 | return Ref<TriangleMesh>(); | 
|---|
| 407 | } | 
|---|
| 408 |  | 
|---|
| 409 | if (surface_get_format(p_surface) & ARRAY_FORMAT_INDEX) { | 
|---|
| 410 | facecount += surface_get_array_index_len(p_surface); | 
|---|
| 411 | } else { | 
|---|
| 412 | facecount += surface_get_array_len(p_surface); | 
|---|
| 413 | } | 
|---|
| 414 |  | 
|---|
| 415 | Vector<Vector3> faces; | 
|---|
| 416 | faces.resize(facecount); | 
|---|
| 417 | Vector3 *facesw = faces.ptrw(); | 
|---|
| 418 |  | 
|---|
| 419 | Array a = surface_get_arrays(p_surface); | 
|---|
| 420 | ERR_FAIL_COND_V(a.is_empty(), Ref<TriangleMesh>()); | 
|---|
| 421 |  | 
|---|
| 422 | int vc = surface_get_array_len(p_surface); | 
|---|
| 423 | Vector<Vector3> vertices = a[ARRAY_VERTEX]; | 
|---|
| 424 | const Vector3 *vr = vertices.ptr(); | 
|---|
| 425 | int widx = 0; | 
|---|
| 426 |  | 
|---|
| 427 | if (surface_get_format(p_surface) & ARRAY_FORMAT_INDEX) { | 
|---|
| 428 | int ic = surface_get_array_index_len(p_surface); | 
|---|
| 429 | Vector<int> indices = a[ARRAY_INDEX]; | 
|---|
| 430 | const int *ir = indices.ptr(); | 
|---|
| 431 |  | 
|---|
| 432 | for (int j = 0; j < ic; j++) { | 
|---|
| 433 | int index = ir[j]; | 
|---|
| 434 | facesw[widx++] = vr[index]; | 
|---|
| 435 | } | 
|---|
| 436 |  | 
|---|
| 437 | } else { | 
|---|
| 438 | for (int j = 0; j < vc; j++) { | 
|---|
| 439 | facesw[widx++] = vr[j]; | 
|---|
| 440 | } | 
|---|
| 441 | } | 
|---|
| 442 |  | 
|---|
| 443 | Ref<TriangleMesh> tr_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); | 
|---|
| 444 | tr_mesh->create(faces); | 
|---|
| 445 | surface_triangle_meshes.set(p_surface, tr_mesh); | 
|---|
| 446 |  | 
|---|
| 447 | return tr_mesh; | 
|---|
| 448 | } | 
|---|
| 449 |  | 
|---|
| 450 | void Mesh::generate_debug_mesh_lines(Vector<Vector3> &r_lines) { | 
|---|
| 451 | if (debug_lines.size() > 0) { | 
|---|
| 452 | r_lines = debug_lines; | 
|---|
| 453 | return; | 
|---|
| 454 | } | 
|---|
| 455 |  | 
|---|
| 456 | Ref<TriangleMesh> tm = generate_triangle_mesh(); | 
|---|
| 457 | if (tm.is_null()) { | 
|---|
| 458 | return; | 
|---|
| 459 | } | 
|---|
| 460 |  | 
|---|
| 461 | Vector<int> triangle_indices; | 
|---|
| 462 | tm->get_indices(&triangle_indices); | 
|---|
| 463 | const int triangles_num = tm->get_triangles().size(); | 
|---|
| 464 | Vector<Vector3> vertices = tm->get_vertices(); | 
|---|
| 465 |  | 
|---|
| 466 | debug_lines.resize(tm->get_triangles().size() * 6); // 3 lines x 2 points each line | 
|---|
| 467 |  | 
|---|
| 468 | const int *ind_r = triangle_indices.ptr(); | 
|---|
| 469 | const Vector3 *ver_r = vertices.ptr(); | 
|---|
| 470 | for (int j = 0, x = 0, i = 0; i < triangles_num; j += 6, x += 3, ++i) { | 
|---|
| 471 | // Triangle line 1 | 
|---|
| 472 | debug_lines.write[j + 0] = ver_r[ind_r[x + 0]]; | 
|---|
| 473 | debug_lines.write[j + 1] = ver_r[ind_r[x + 1]]; | 
|---|
| 474 |  | 
|---|
| 475 | // Triangle line 2 | 
|---|
| 476 | debug_lines.write[j + 2] = ver_r[ind_r[x + 1]]; | 
|---|
| 477 | debug_lines.write[j + 3] = ver_r[ind_r[x + 2]]; | 
|---|
| 478 |  | 
|---|
| 479 | // Triangle line 3 | 
|---|
| 480 | debug_lines.write[j + 4] = ver_r[ind_r[x + 2]]; | 
|---|
| 481 | debug_lines.write[j + 5] = ver_r[ind_r[x + 0]]; | 
|---|
| 482 | } | 
|---|
| 483 |  | 
|---|
| 484 | r_lines = debug_lines; | 
|---|
| 485 | } | 
|---|
| 486 |  | 
|---|
| 487 | void Mesh::generate_debug_mesh_indices(Vector<Vector3> &r_points) { | 
|---|
| 488 | Ref<TriangleMesh> tm = generate_triangle_mesh(); | 
|---|
| 489 | if (tm.is_null()) { | 
|---|
| 490 | return; | 
|---|
| 491 | } | 
|---|
| 492 |  | 
|---|
| 493 | Vector<Vector3> vertices = tm->get_vertices(); | 
|---|
| 494 |  | 
|---|
| 495 | int vertices_size = vertices.size(); | 
|---|
| 496 | r_points.resize(vertices_size); | 
|---|
| 497 | for (int i = 0; i < vertices_size; ++i) { | 
|---|
| 498 | r_points.write[i] = vertices[i]; | 
|---|
| 499 | } | 
|---|
| 500 | } | 
|---|
| 501 |  | 
|---|
| 502 | Vector<Vector3> Mesh::_get_faces() const { | 
|---|
| 503 | return Variant(get_faces()); | 
|---|
| 504 | } | 
|---|
| 505 |  | 
|---|
| 506 | Vector<Face3> Mesh::get_faces() const { | 
|---|
| 507 | Ref<TriangleMesh> tm = generate_triangle_mesh(); | 
|---|
| 508 | if (tm.is_valid()) { | 
|---|
| 509 | return tm->get_faces(); | 
|---|
| 510 | } | 
|---|
| 511 | return Vector<Face3>(); | 
|---|
| 512 | } | 
|---|
| 513 |  | 
|---|
| 514 | Vector<Face3> Mesh::get_surface_faces(int p_surface) const { | 
|---|
| 515 | Ref<TriangleMesh> tm = generate_surface_triangle_mesh(p_surface); | 
|---|
| 516 | if (tm.is_valid()) { | 
|---|
| 517 | return tm->get_faces(); | 
|---|
| 518 | } | 
|---|
| 519 | return Vector<Face3>(); | 
|---|
| 520 | } | 
|---|
| 521 |  | 
|---|
| 522 | Ref<ConvexPolygonShape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const { | 
|---|
| 523 | if (p_simplify) { | 
|---|
| 524 | Ref<MeshConvexDecompositionSettings> settings = Ref<MeshConvexDecompositionSettings>(); | 
|---|
| 525 | settings.instantiate(); | 
|---|
| 526 | settings->set_max_convex_hulls(1); | 
|---|
| 527 | settings->set_max_concavity(1.0); | 
|---|
| 528 | Vector<Ref<Shape3D>> decomposed = convex_decompose(settings); | 
|---|
| 529 | if (decomposed.size() == 1) { | 
|---|
| 530 | return decomposed[0]; | 
|---|
| 531 | } else { | 
|---|
| 532 | ERR_PRINT( "Convex shape simplification failed, falling back to simpler process."); | 
|---|
| 533 | } | 
|---|
| 534 | } | 
|---|
| 535 |  | 
|---|
| 536 | Vector<Vector3> vertices; | 
|---|
| 537 | for (int i = 0; i < get_surface_count(); i++) { | 
|---|
| 538 | Array a = surface_get_arrays(i); | 
|---|
| 539 | ERR_FAIL_COND_V(a.is_empty(), Ref<ConvexPolygonShape3D>()); | 
|---|
| 540 | Vector<Vector3> v = a[ARRAY_VERTEX]; | 
|---|
| 541 | vertices.append_array(v); | 
|---|
| 542 | } | 
|---|
| 543 |  | 
|---|
| 544 | Ref<ConvexPolygonShape3D> shape = memnew(ConvexPolygonShape3D); | 
|---|
| 545 |  | 
|---|
| 546 | if (p_clean) { | 
|---|
| 547 | Geometry3D::MeshData md; | 
|---|
| 548 | Error err = ConvexHullComputer::convex_hull(vertices, md); | 
|---|
| 549 | if (err == OK) { | 
|---|
| 550 | shape->set_points(md.vertices); | 
|---|
| 551 | return shape; | 
|---|
| 552 | } else { | 
|---|
| 553 | ERR_PRINT( "Convex shape cleaning failed, falling back to simpler process."); | 
|---|
| 554 | } | 
|---|
| 555 | } | 
|---|
| 556 |  | 
|---|
| 557 | shape->set_points(vertices); | 
|---|
| 558 | return shape; | 
|---|
| 559 | } | 
|---|
| 560 |  | 
|---|
| 561 | Ref<ConcavePolygonShape3D> Mesh::create_trimesh_shape() const { | 
|---|
| 562 | Vector<Face3> faces = get_faces(); | 
|---|
| 563 | if (faces.size() == 0) { | 
|---|
| 564 | return Ref<ConcavePolygonShape3D>(); | 
|---|
| 565 | } | 
|---|
| 566 |  | 
|---|
| 567 | Vector<Vector3> face_points; | 
|---|
| 568 | face_points.resize(faces.size() * 3); | 
|---|
| 569 |  | 
|---|
| 570 | for (int i = 0; i < face_points.size(); i += 3) { | 
|---|
| 571 | Face3 f = faces.get(i / 3); | 
|---|
| 572 | face_points.set(i, f.vertex[0]); | 
|---|
| 573 | face_points.set(i + 1, f.vertex[1]); | 
|---|
| 574 | face_points.set(i + 2, f.vertex[2]); | 
|---|
| 575 | } | 
|---|
| 576 |  | 
|---|
| 577 | Ref<ConcavePolygonShape3D> shape = memnew(ConcavePolygonShape3D); | 
|---|
| 578 | shape->set_faces(face_points); | 
|---|
| 579 | return shape; | 
|---|
| 580 | } | 
|---|
| 581 |  | 
|---|
| 582 | Ref<Mesh> Mesh::create_outline(float p_margin) const { | 
|---|
| 583 | Array arrays; | 
|---|
| 584 | int index_accum = 0; | 
|---|
| 585 | for (int i = 0; i < get_surface_count(); i++) { | 
|---|
| 586 | if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) { | 
|---|
| 587 | continue; | 
|---|
| 588 | } | 
|---|
| 589 |  | 
|---|
| 590 | Array a = surface_get_arrays(i); | 
|---|
| 591 | ERR_FAIL_COND_V(a.is_empty(), Ref<ArrayMesh>()); | 
|---|
| 592 |  | 
|---|
| 593 | if (i == 0) { | 
|---|
| 594 | arrays = a; | 
|---|
| 595 | Vector<Vector3> v = a[ARRAY_VERTEX]; | 
|---|
| 596 | index_accum += v.size(); | 
|---|
| 597 | } else { | 
|---|
| 598 | int vcount = 0; | 
|---|
| 599 | for (int j = 0; j < arrays.size(); j++) { | 
|---|
| 600 | if (arrays[j].get_type() == Variant::NIL || a[j].get_type() == Variant::NIL) { | 
|---|
| 601 | //mismatch, do not use | 
|---|
| 602 | arrays[j] = Variant(); | 
|---|
| 603 | continue; | 
|---|
| 604 | } | 
|---|
| 605 |  | 
|---|
| 606 | switch (j) { | 
|---|
| 607 | case ARRAY_VERTEX: | 
|---|
| 608 | case ARRAY_NORMAL: { | 
|---|
| 609 | Vector<Vector3> dst = arrays[j]; | 
|---|
| 610 | Vector<Vector3> src = a[j]; | 
|---|
| 611 | if (j == ARRAY_VERTEX) { | 
|---|
| 612 | vcount = src.size(); | 
|---|
| 613 | } | 
|---|
| 614 | if (dst.size() == 0 || src.size() == 0) { | 
|---|
| 615 | arrays[j] = Variant(); | 
|---|
| 616 | continue; | 
|---|
| 617 | } | 
|---|
| 618 | dst.append_array(src); | 
|---|
| 619 | arrays[j] = dst; | 
|---|
| 620 | } break; | 
|---|
| 621 | case ARRAY_TANGENT: | 
|---|
| 622 | case ARRAY_BONES: | 
|---|
| 623 | case ARRAY_WEIGHTS: { | 
|---|
| 624 | Vector<real_t> dst = arrays[j]; | 
|---|
| 625 | Vector<real_t> src = a[j]; | 
|---|
| 626 | if (dst.size() == 0 || src.size() == 0) { | 
|---|
| 627 | arrays[j] = Variant(); | 
|---|
| 628 | continue; | 
|---|
| 629 | } | 
|---|
| 630 | dst.append_array(src); | 
|---|
| 631 | arrays[j] = dst; | 
|---|
| 632 |  | 
|---|
| 633 | } break; | 
|---|
| 634 | case ARRAY_COLOR: { | 
|---|
| 635 | Vector<Color> dst = arrays[j]; | 
|---|
| 636 | Vector<Color> src = a[j]; | 
|---|
| 637 | if (dst.size() == 0 || src.size() == 0) { | 
|---|
| 638 | arrays[j] = Variant(); | 
|---|
| 639 | continue; | 
|---|
| 640 | } | 
|---|
| 641 | dst.append_array(src); | 
|---|
| 642 | arrays[j] = dst; | 
|---|
| 643 |  | 
|---|
| 644 | } break; | 
|---|
| 645 | case ARRAY_TEX_UV: | 
|---|
| 646 | case ARRAY_TEX_UV2: { | 
|---|
| 647 | Vector<Vector2> dst = arrays[j]; | 
|---|
| 648 | Vector<Vector2> src = a[j]; | 
|---|
| 649 | if (dst.size() == 0 || src.size() == 0) { | 
|---|
| 650 | arrays[j] = Variant(); | 
|---|
| 651 | continue; | 
|---|
| 652 | } | 
|---|
| 653 | dst.append_array(src); | 
|---|
| 654 | arrays[j] = dst; | 
|---|
| 655 |  | 
|---|
| 656 | } break; | 
|---|
| 657 | case ARRAY_INDEX: { | 
|---|
| 658 | Vector<int> dst = arrays[j]; | 
|---|
| 659 | Vector<int> src = a[j]; | 
|---|
| 660 | if (dst.size() == 0 || src.size() == 0) { | 
|---|
| 661 | arrays[j] = Variant(); | 
|---|
| 662 | continue; | 
|---|
| 663 | } | 
|---|
| 664 | { | 
|---|
| 665 | int ss = src.size(); | 
|---|
| 666 | int *w = src.ptrw(); | 
|---|
| 667 | for (int k = 0; k < ss; k++) { | 
|---|
| 668 | w[k] += index_accum; | 
|---|
| 669 | } | 
|---|
| 670 | } | 
|---|
| 671 | dst.append_array(src); | 
|---|
| 672 | arrays[j] = dst; | 
|---|
| 673 | index_accum += vcount; | 
|---|
| 674 |  | 
|---|
| 675 | } break; | 
|---|
| 676 | } | 
|---|
| 677 | } | 
|---|
| 678 | } | 
|---|
| 679 | } | 
|---|
| 680 |  | 
|---|
| 681 | ERR_FAIL_COND_V(arrays.size() != ARRAY_MAX, Ref<ArrayMesh>()); | 
|---|
| 682 |  | 
|---|
| 683 | { | 
|---|
| 684 | int *ir = nullptr; | 
|---|
| 685 | Vector<int> indices = arrays[ARRAY_INDEX]; | 
|---|
| 686 | bool has_indices = false; | 
|---|
| 687 | Vector<Vector3> vertices = arrays[ARRAY_VERTEX]; | 
|---|
| 688 | int vc = vertices.size(); | 
|---|
| 689 | ERR_FAIL_COND_V(!vc, Ref<ArrayMesh>()); | 
|---|
| 690 | Vector3 *r = vertices.ptrw(); | 
|---|
| 691 |  | 
|---|
| 692 | if (indices.size()) { | 
|---|
| 693 | ERR_FAIL_COND_V(indices.size() % 3 != 0, Ref<ArrayMesh>()); | 
|---|
| 694 | vc = indices.size(); | 
|---|
| 695 | ir = indices.ptrw(); | 
|---|
| 696 | has_indices = true; | 
|---|
| 697 | } else { | 
|---|
| 698 | // Ensure there are enough vertices to construct at least one triangle. | 
|---|
| 699 | ERR_FAIL_COND_V(vertices.size() % 3 != 0, Ref<ArrayMesh>()); | 
|---|
| 700 | } | 
|---|
| 701 |  | 
|---|
| 702 | HashMap<Vector3, Vector3> normal_accum; | 
|---|
| 703 |  | 
|---|
| 704 | //fill normals with triangle normals | 
|---|
| 705 | for (int i = 0; i < vc; i += 3) { | 
|---|
| 706 | Vector3 t[3]; | 
|---|
| 707 |  | 
|---|
| 708 | if (has_indices) { | 
|---|
| 709 | t[0] = r[ir[i + 0]]; | 
|---|
| 710 | t[1] = r[ir[i + 1]]; | 
|---|
| 711 | t[2] = r[ir[i + 2]]; | 
|---|
| 712 | } else { | 
|---|
| 713 | t[0] = r[i + 0]; | 
|---|
| 714 | t[1] = r[i + 1]; | 
|---|
| 715 | t[2] = r[i + 2]; | 
|---|
| 716 | } | 
|---|
| 717 |  | 
|---|
| 718 | Vector3 n = Plane(t[0], t[1], t[2]).normal; | 
|---|
| 719 |  | 
|---|
| 720 | for (int j = 0; j < 3; j++) { | 
|---|
| 721 | HashMap<Vector3, Vector3>::Iterator E = normal_accum.find(t[j]); | 
|---|
| 722 | if (!E) { | 
|---|
| 723 | normal_accum[t[j]] = n; | 
|---|
| 724 | } else { | 
|---|
| 725 | float d = n.dot(E->value); | 
|---|
| 726 | if (d < 1.0) { | 
|---|
| 727 | E->value += n * (1.0 - d); | 
|---|
| 728 | } | 
|---|
| 729 | //E->get()+=n; | 
|---|
| 730 | } | 
|---|
| 731 | } | 
|---|
| 732 | } | 
|---|
| 733 |  | 
|---|
| 734 | //normalize | 
|---|
| 735 |  | 
|---|
| 736 | for (KeyValue<Vector3, Vector3> &E : normal_accum) { | 
|---|
| 737 | E.value.normalize(); | 
|---|
| 738 | } | 
|---|
| 739 |  | 
|---|
| 740 | //displace normals | 
|---|
| 741 | int vc2 = vertices.size(); | 
|---|
| 742 |  | 
|---|
| 743 | for (int i = 0; i < vc2; i++) { | 
|---|
| 744 | Vector3 t = r[i]; | 
|---|
| 745 |  | 
|---|
| 746 | HashMap<Vector3, Vector3>::Iterator E = normal_accum.find(t); | 
|---|
| 747 | ERR_CONTINUE(!E); | 
|---|
| 748 |  | 
|---|
| 749 | t += E->value * p_margin; | 
|---|
| 750 | r[i] = t; | 
|---|
| 751 | } | 
|---|
| 752 |  | 
|---|
| 753 | arrays[ARRAY_VERTEX] = vertices; | 
|---|
| 754 |  | 
|---|
| 755 | if (!has_indices) { | 
|---|
| 756 | Vector<int> new_indices; | 
|---|
| 757 | new_indices.resize(vertices.size()); | 
|---|
| 758 | int *iw = new_indices.ptrw(); | 
|---|
| 759 |  | 
|---|
| 760 | for (int j = 0; j < vc2; j += 3) { | 
|---|
| 761 | iw[j] = j; | 
|---|
| 762 | iw[j + 1] = j + 2; | 
|---|
| 763 | iw[j + 2] = j + 1; | 
|---|
| 764 | } | 
|---|
| 765 |  | 
|---|
| 766 | arrays[ARRAY_INDEX] = new_indices; | 
|---|
| 767 |  | 
|---|
| 768 | } else { | 
|---|
| 769 | for (int j = 0; j < vc; j += 3) { | 
|---|
| 770 | SWAP(ir[j + 1], ir[j + 2]); | 
|---|
| 771 | } | 
|---|
| 772 | arrays[ARRAY_INDEX] = indices; | 
|---|
| 773 | } | 
|---|
| 774 | } | 
|---|
| 775 |  | 
|---|
| 776 | Ref<ArrayMesh> newmesh = memnew(ArrayMesh); | 
|---|
| 777 | newmesh->add_surface_from_arrays(PRIMITIVE_TRIANGLES, arrays); | 
|---|
| 778 | return newmesh; | 
|---|
| 779 | } | 
|---|
| 780 |  | 
|---|
| 781 | void Mesh::set_lightmap_size_hint(const Size2i &p_size) { | 
|---|
| 782 | lightmap_size_hint = p_size; | 
|---|
| 783 | } | 
|---|
| 784 |  | 
|---|
| 785 | Size2i Mesh::get_lightmap_size_hint() const { | 
|---|
| 786 | return lightmap_size_hint; | 
|---|
| 787 | } | 
|---|
| 788 |  | 
|---|
| 789 | Ref<Resource> Mesh::create_placeholder() const { | 
|---|
| 790 | Ref<PlaceholderMesh> placeholder; | 
|---|
| 791 | placeholder.instantiate(); | 
|---|
| 792 | placeholder->set_aabb(get_aabb()); | 
|---|
| 793 | return placeholder; | 
|---|
| 794 | } | 
|---|
| 795 |  | 
|---|
| 796 | void Mesh::_bind_methods() { | 
|---|
| 797 | ClassDB::bind_method(D_METHOD( "set_lightmap_size_hint", "size"), &Mesh::set_lightmap_size_hint); | 
|---|
| 798 | ClassDB::bind_method(D_METHOD( "get_lightmap_size_hint"), &Mesh::get_lightmap_size_hint); | 
|---|
| 799 | ClassDB::bind_method(D_METHOD( "get_aabb"), &Mesh::get_aabb); | 
|---|
| 800 | ClassDB::bind_method(D_METHOD( "get_faces"), &Mesh::_get_faces); | 
|---|
| 801 |  | 
|---|
| 802 | ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "lightmap_size_hint"), "set_lightmap_size_hint", "get_lightmap_size_hint"); | 
|---|
| 803 |  | 
|---|
| 804 | ClassDB::bind_method(D_METHOD( "get_surface_count"), &Mesh::get_surface_count); | 
|---|
| 805 | ClassDB::bind_method(D_METHOD( "surface_get_arrays", "surf_idx"), &Mesh::surface_get_arrays); | 
|---|
| 806 | ClassDB::bind_method(D_METHOD( "surface_get_blend_shape_arrays", "surf_idx"), &Mesh::surface_get_blend_shape_arrays); | 
|---|
| 807 | ClassDB::bind_method(D_METHOD( "surface_set_material", "surf_idx", "material"), &Mesh::surface_set_material); | 
|---|
| 808 | ClassDB::bind_method(D_METHOD( "surface_get_material", "surf_idx"), &Mesh::surface_get_material); | 
|---|
| 809 | ClassDB::bind_method(D_METHOD( "create_placeholder"), &Mesh::create_placeholder); | 
|---|
| 810 |  | 
|---|
| 811 | BIND_ENUM_CONSTANT(PRIMITIVE_POINTS); | 
|---|
| 812 | BIND_ENUM_CONSTANT(PRIMITIVE_LINES); | 
|---|
| 813 | BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP); | 
|---|
| 814 | BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLES); | 
|---|
| 815 | BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_STRIP); | 
|---|
| 816 |  | 
|---|
| 817 | BIND_ENUM_CONSTANT(ARRAY_VERTEX); | 
|---|
| 818 | BIND_ENUM_CONSTANT(ARRAY_NORMAL); | 
|---|
| 819 | BIND_ENUM_CONSTANT(ARRAY_TANGENT); | 
|---|
| 820 | BIND_ENUM_CONSTANT(ARRAY_COLOR); | 
|---|
| 821 | BIND_ENUM_CONSTANT(ARRAY_TEX_UV); | 
|---|
| 822 | BIND_ENUM_CONSTANT(ARRAY_TEX_UV2); | 
|---|
| 823 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM0); | 
|---|
| 824 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM1); | 
|---|
| 825 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM2); | 
|---|
| 826 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM3); | 
|---|
| 827 | BIND_ENUM_CONSTANT(ARRAY_BONES); | 
|---|
| 828 | BIND_ENUM_CONSTANT(ARRAY_WEIGHTS); | 
|---|
| 829 | BIND_ENUM_CONSTANT(ARRAY_INDEX); | 
|---|
| 830 | BIND_ENUM_CONSTANT(ARRAY_MAX); | 
|---|
| 831 |  | 
|---|
| 832 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_UNORM); | 
|---|
| 833 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_SNORM); | 
|---|
| 834 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_HALF); | 
|---|
| 835 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_HALF); | 
|---|
| 836 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_R_FLOAT); | 
|---|
| 837 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_FLOAT); | 
|---|
| 838 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGB_FLOAT); | 
|---|
| 839 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_FLOAT); | 
|---|
| 840 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_MAX); | 
|---|
| 841 |  | 
|---|
| 842 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_VERTEX); | 
|---|
| 843 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_NORMAL); | 
|---|
| 844 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_TANGENT); | 
|---|
| 845 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_COLOR); | 
|---|
| 846 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_TEX_UV); | 
|---|
| 847 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_TEX_UV2); | 
|---|
| 848 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM0); | 
|---|
| 849 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM1); | 
|---|
| 850 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM2); | 
|---|
| 851 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM3); | 
|---|
| 852 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_BONES); | 
|---|
| 853 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_WEIGHTS); | 
|---|
| 854 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_INDEX); | 
|---|
| 855 |  | 
|---|
| 856 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_BLEND_SHAPE_MASK); | 
|---|
| 857 |  | 
|---|
| 858 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM_BASE); | 
|---|
| 859 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM_BITS); | 
|---|
| 860 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM0_SHIFT); | 
|---|
| 861 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM1_SHIFT); | 
|---|
| 862 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM2_SHIFT); | 
|---|
| 863 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM3_SHIFT); | 
|---|
| 864 |  | 
|---|
| 865 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM_MASK); | 
|---|
| 866 | BIND_BITFIELD_FLAG(ARRAY_COMPRESS_FLAGS_BASE); | 
|---|
| 867 |  | 
|---|
| 868 | BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_2D_VERTICES); | 
|---|
| 869 | BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_DYNAMIC_UPDATE); | 
|---|
| 870 | BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_8_BONE_WEIGHTS); | 
|---|
| 871 | BIND_BITFIELD_FLAG(ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY); | 
|---|
| 872 |  | 
|---|
| 873 | BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED); | 
|---|
| 874 | BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE); | 
|---|
| 875 |  | 
|---|
| 876 | GDVIRTUAL_BIND(_get_surface_count) | 
|---|
| 877 | GDVIRTUAL_BIND(_surface_get_array_len, "index") | 
|---|
| 878 | GDVIRTUAL_BIND(_surface_get_array_index_len, "index") | 
|---|
| 879 | GDVIRTUAL_BIND(_surface_get_arrays, "index") | 
|---|
| 880 | GDVIRTUAL_BIND(_surface_get_blend_shape_arrays, "index") | 
|---|
| 881 | GDVIRTUAL_BIND(_surface_get_lods, "index") | 
|---|
| 882 | GDVIRTUAL_BIND(_surface_get_format, "index") | 
|---|
| 883 | GDVIRTUAL_BIND(_surface_get_primitive_type, "index") | 
|---|
| 884 | GDVIRTUAL_BIND(_surface_set_material, "index", "material") | 
|---|
| 885 | GDVIRTUAL_BIND(_surface_get_material, "index") | 
|---|
| 886 | GDVIRTUAL_BIND(_get_blend_shape_count) | 
|---|
| 887 | GDVIRTUAL_BIND(_get_blend_shape_name, "index") | 
|---|
| 888 | GDVIRTUAL_BIND(_set_blend_shape_name, "index", "name") | 
|---|
| 889 | GDVIRTUAL_BIND(_get_aabb) | 
|---|
| 890 | } | 
|---|
| 891 |  | 
|---|
| 892 | void Mesh::clear_cache() const { | 
|---|
| 893 | triangle_mesh.unref(); | 
|---|
| 894 | debug_lines.clear(); | 
|---|
| 895 | } | 
|---|
| 896 |  | 
|---|
| 897 | Vector<Ref<Shape3D>> Mesh::convex_decompose(const Ref<MeshConvexDecompositionSettings> &p_settings) const { | 
|---|
| 898 | ERR_FAIL_NULL_V(convex_decomposition_function, Vector<Ref<Shape3D>>()); | 
|---|
| 899 |  | 
|---|
| 900 | Ref<TriangleMesh> tm = generate_triangle_mesh(); | 
|---|
| 901 | ERR_FAIL_COND_V(!tm.is_valid(), Vector<Ref<Shape3D>>()); | 
|---|
| 902 |  | 
|---|
| 903 | const Vector<TriangleMesh::Triangle> &triangles = tm->get_triangles(); | 
|---|
| 904 | int triangle_count = triangles.size(); | 
|---|
| 905 |  | 
|---|
| 906 | Vector<uint32_t> indices; | 
|---|
| 907 | { | 
|---|
| 908 | indices.resize(triangle_count * 3); | 
|---|
| 909 | uint32_t *w = indices.ptrw(); | 
|---|
| 910 | for (int i = 0; i < triangle_count; i++) { | 
|---|
| 911 | for (int j = 0; j < 3; j++) { | 
|---|
| 912 | w[i * 3 + j] = triangles[i].indices[j]; | 
|---|
| 913 | } | 
|---|
| 914 | } | 
|---|
| 915 | } | 
|---|
| 916 |  | 
|---|
| 917 | const Vector<Vector3> &vertices = tm->get_vertices(); | 
|---|
| 918 | int vertex_count = vertices.size(); | 
|---|
| 919 |  | 
|---|
| 920 | Vector<Vector<Vector3>> decomposed = convex_decomposition_function((real_t *)vertices.ptr(), vertex_count, indices.ptr(), triangle_count, p_settings, nullptr); | 
|---|
| 921 |  | 
|---|
| 922 | Vector<Ref<Shape3D>> ret; | 
|---|
| 923 |  | 
|---|
| 924 | for (int i = 0; i < decomposed.size(); i++) { | 
|---|
| 925 | Ref<ConvexPolygonShape3D> shape; | 
|---|
| 926 | shape.instantiate(); | 
|---|
| 927 | shape->set_points(decomposed[i]); | 
|---|
| 928 | ret.push_back(shape); | 
|---|
| 929 | } | 
|---|
| 930 |  | 
|---|
| 931 | return ret; | 
|---|
| 932 | } | 
|---|
| 933 |  | 
|---|
| 934 | int Mesh::get_builtin_bind_pose_count() const { | 
|---|
| 935 | return 0; | 
|---|
| 936 | } | 
|---|
| 937 |  | 
|---|
| 938 | Transform3D Mesh::get_builtin_bind_pose(int p_index) const { | 
|---|
| 939 | return Transform3D(); | 
|---|
| 940 | } | 
|---|
| 941 |  | 
|---|
| 942 | Mesh::Mesh() { | 
|---|
| 943 | } | 
|---|
| 944 |  | 
|---|
| 945 | enum OldArrayType { | 
|---|
| 946 | OLD_ARRAY_VERTEX, | 
|---|
| 947 | OLD_ARRAY_NORMAL, | 
|---|
| 948 | OLD_ARRAY_TANGENT, | 
|---|
| 949 | OLD_ARRAY_COLOR, | 
|---|
| 950 | OLD_ARRAY_TEX_UV, | 
|---|
| 951 | OLD_ARRAY_TEX_UV2, | 
|---|
| 952 | OLD_ARRAY_BONES, | 
|---|
| 953 | OLD_ARRAY_WEIGHTS, | 
|---|
| 954 | OLD_ARRAY_INDEX, | 
|---|
| 955 | OLD_ARRAY_MAX, | 
|---|
| 956 | }; | 
|---|
| 957 |  | 
|---|
| 958 | enum OldArrayFormat { | 
|---|
| 959 | /* OLD_ARRAY FORMAT FLAGS */ | 
|---|
| 960 | OLD_ARRAY_FORMAT_VERTEX = 1 << OLD_ARRAY_VERTEX, // mandatory | 
|---|
| 961 | OLD_ARRAY_FORMAT_NORMAL = 1 << OLD_ARRAY_NORMAL, | 
|---|
| 962 | OLD_ARRAY_FORMAT_TANGENT = 1 << OLD_ARRAY_TANGENT, | 
|---|
| 963 | OLD_ARRAY_FORMAT_COLOR = 1 << OLD_ARRAY_COLOR, | 
|---|
| 964 | OLD_ARRAY_FORMAT_TEX_UV = 1 << OLD_ARRAY_TEX_UV, | 
|---|
| 965 | OLD_ARRAY_FORMAT_TEX_UV2 = 1 << OLD_ARRAY_TEX_UV2, | 
|---|
| 966 | OLD_ARRAY_FORMAT_BONES = 1 << OLD_ARRAY_BONES, | 
|---|
| 967 | OLD_ARRAY_FORMAT_WEIGHTS = 1 << OLD_ARRAY_WEIGHTS, | 
|---|
| 968 | OLD_ARRAY_FORMAT_INDEX = 1 << OLD_ARRAY_INDEX, | 
|---|
| 969 |  | 
|---|
| 970 | OLD_ARRAY_COMPRESS_BASE = (OLD_ARRAY_INDEX + 1), | 
|---|
| 971 | OLD_ARRAY_COMPRESS_VERTEX = 1 << (OLD_ARRAY_VERTEX + OLD_ARRAY_COMPRESS_BASE), // mandatory | 
|---|
| 972 | OLD_ARRAY_COMPRESS_NORMAL = 1 << (OLD_ARRAY_NORMAL + OLD_ARRAY_COMPRESS_BASE), | 
|---|
| 973 | OLD_ARRAY_COMPRESS_TANGENT = 1 << (OLD_ARRAY_TANGENT + OLD_ARRAY_COMPRESS_BASE), | 
|---|
| 974 | OLD_ARRAY_COMPRESS_COLOR = 1 << (OLD_ARRAY_COLOR + OLD_ARRAY_COMPRESS_BASE), | 
|---|
| 975 | OLD_ARRAY_COMPRESS_TEX_UV = 1 << (OLD_ARRAY_TEX_UV + OLD_ARRAY_COMPRESS_BASE), | 
|---|
| 976 | OLD_ARRAY_COMPRESS_TEX_UV2 = 1 << (OLD_ARRAY_TEX_UV2 + OLD_ARRAY_COMPRESS_BASE), | 
|---|
| 977 | OLD_ARRAY_COMPRESS_BONES = 1 << (OLD_ARRAY_BONES + OLD_ARRAY_COMPRESS_BASE), | 
|---|
| 978 | OLD_ARRAY_COMPRESS_WEIGHTS = 1 << (OLD_ARRAY_WEIGHTS + OLD_ARRAY_COMPRESS_BASE), | 
|---|
| 979 | OLD_ARRAY_COMPRESS_INDEX = 1 << (OLD_ARRAY_INDEX + OLD_ARRAY_COMPRESS_BASE), | 
|---|
| 980 |  | 
|---|
| 981 | OLD_ARRAY_FLAG_USE_2D_VERTICES = OLD_ARRAY_COMPRESS_INDEX << 1, | 
|---|
| 982 | OLD_ARRAY_FLAG_USE_16_BIT_BONES = OLD_ARRAY_COMPRESS_INDEX << 2, | 
|---|
| 983 | OLD_ARRAY_FLAG_USE_DYNAMIC_UPDATE = OLD_ARRAY_COMPRESS_INDEX << 3, | 
|---|
| 984 | OLD_ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION = OLD_ARRAY_COMPRESS_INDEX << 4, | 
|---|
| 985 | }; | 
|---|
| 986 |  | 
|---|
| 987 | #ifndef DISABLE_DEPRECATED | 
|---|
| 988 | static Array _convert_old_array(const Array &p_old) { | 
|---|
| 989 | Array new_array; | 
|---|
| 990 | new_array.resize(Mesh::ARRAY_MAX); | 
|---|
| 991 | new_array[Mesh::ARRAY_VERTEX] = p_old[OLD_ARRAY_VERTEX]; | 
|---|
| 992 | new_array[Mesh::ARRAY_NORMAL] = p_old[OLD_ARRAY_NORMAL]; | 
|---|
| 993 | new_array[Mesh::ARRAY_TANGENT] = p_old[OLD_ARRAY_TANGENT]; | 
|---|
| 994 | new_array[Mesh::ARRAY_COLOR] = p_old[OLD_ARRAY_COLOR]; | 
|---|
| 995 | new_array[Mesh::ARRAY_TEX_UV] = p_old[OLD_ARRAY_TEX_UV]; | 
|---|
| 996 | new_array[Mesh::ARRAY_TEX_UV2] = p_old[OLD_ARRAY_TEX_UV2]; | 
|---|
| 997 | new_array[Mesh::ARRAY_BONES] = p_old[OLD_ARRAY_BONES]; | 
|---|
| 998 | new_array[Mesh::ARRAY_WEIGHTS] = p_old[OLD_ARRAY_WEIGHTS]; | 
|---|
| 999 | new_array[Mesh::ARRAY_INDEX] = p_old[OLD_ARRAY_INDEX]; | 
|---|
| 1000 | return new_array; | 
|---|
| 1001 | } | 
|---|
| 1002 |  | 
|---|
| 1003 | static Mesh::PrimitiveType _old_primitives[7] = { | 
|---|
| 1004 | Mesh::PRIMITIVE_POINTS, | 
|---|
| 1005 | Mesh::PRIMITIVE_LINES, | 
|---|
| 1006 | Mesh::PRIMITIVE_LINE_STRIP, | 
|---|
| 1007 | Mesh::PRIMITIVE_LINES, | 
|---|
| 1008 | Mesh::PRIMITIVE_TRIANGLES, | 
|---|
| 1009 | Mesh::PRIMITIVE_TRIANGLE_STRIP, | 
|---|
| 1010 | Mesh::PRIMITIVE_TRIANGLE_STRIP | 
|---|
| 1011 | }; | 
|---|
| 1012 | #endif // DISABLE_DEPRECATED | 
|---|
| 1013 |  | 
|---|
| 1014 | void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_format, uint32_t p_new_format, uint32_t p_elements, Vector<uint8_t> &vertex_data, Vector<uint8_t> &attribute_data, Vector<uint8_t> &skin_data) { | 
|---|
| 1015 | uint32_t dst_vertex_stride; | 
|---|
| 1016 | uint32_t dst_attribute_stride; | 
|---|
| 1017 | uint32_t dst_skin_stride; | 
|---|
| 1018 | uint32_t dst_offsets[Mesh::ARRAY_MAX]; | 
|---|
| 1019 | RenderingServer::get_singleton()->mesh_surface_make_offsets_from_format(p_new_format & (~RS::ARRAY_FORMAT_INDEX), p_elements, 0, dst_offsets, dst_vertex_stride, dst_attribute_stride, dst_skin_stride); | 
|---|
| 1020 |  | 
|---|
| 1021 | vertex_data.resize(dst_vertex_stride * p_elements); | 
|---|
| 1022 | attribute_data.resize(dst_attribute_stride * p_elements); | 
|---|
| 1023 | skin_data.resize(dst_skin_stride * p_elements); | 
|---|
| 1024 |  | 
|---|
| 1025 | uint8_t *dst_vertex_ptr = vertex_data.ptrw(); | 
|---|
| 1026 | uint8_t *dst_attribute_ptr = attribute_data.ptrw(); | 
|---|
| 1027 | uint8_t *dst_skin_ptr = skin_data.ptrw(); | 
|---|
| 1028 |  | 
|---|
| 1029 | const uint8_t *src_vertex_ptr = p_src.ptr(); | 
|---|
| 1030 | uint32_t src_vertex_stride = p_src.size() / p_elements; | 
|---|
| 1031 |  | 
|---|
| 1032 | uint32_t src_offset = 0; | 
|---|
| 1033 | for (uint32_t j = 0; j < OLD_ARRAY_INDEX; j++) { | 
|---|
| 1034 | if (!(p_old_format & (1 << j))) { | 
|---|
| 1035 | continue; | 
|---|
| 1036 | } | 
|---|
| 1037 | switch (j) { | 
|---|
| 1038 | case OLD_ARRAY_VERTEX: { | 
|---|
| 1039 | if (p_old_format & OLD_ARRAY_FLAG_USE_2D_VERTICES) { | 
|---|
| 1040 | if (p_old_format & OLD_ARRAY_COMPRESS_VERTEX) { | 
|---|
| 1041 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1042 | const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride]; | 
|---|
| 1043 | float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; | 
|---|
| 1044 | dst[0] = Math::half_to_float(src[0]); | 
|---|
| 1045 | dst[1] = Math::half_to_float(src[1]); | 
|---|
| 1046 | } | 
|---|
| 1047 | src_offset += sizeof(uint16_t) * 2; | 
|---|
| 1048 | } else { | 
|---|
| 1049 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1050 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride]; | 
|---|
| 1051 | float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; | 
|---|
| 1052 | dst[0] = src[0]; | 
|---|
| 1053 | dst[1] = src[1]; | 
|---|
| 1054 | } | 
|---|
| 1055 | src_offset += sizeof(float) * 2; | 
|---|
| 1056 | } | 
|---|
| 1057 | } else { | 
|---|
| 1058 | if (p_old_format & OLD_ARRAY_COMPRESS_VERTEX) { | 
|---|
| 1059 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1060 | const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride]; | 
|---|
| 1061 | float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; | 
|---|
| 1062 | dst[0] = Math::half_to_float(src[0]); | 
|---|
| 1063 | dst[1] = Math::half_to_float(src[1]); | 
|---|
| 1064 | dst[2] = Math::half_to_float(src[2]); | 
|---|
| 1065 | } | 
|---|
| 1066 | src_offset += sizeof(uint16_t) * 4; //+pad | 
|---|
| 1067 | } else { | 
|---|
| 1068 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1069 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride]; | 
|---|
| 1070 | float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; | 
|---|
| 1071 | dst[0] = src[0]; | 
|---|
| 1072 | dst[1] = src[1]; | 
|---|
| 1073 | dst[2] = src[2]; | 
|---|
| 1074 | } | 
|---|
| 1075 | src_offset += sizeof(float) * 3; | 
|---|
| 1076 | } | 
|---|
| 1077 | } | 
|---|
| 1078 | } break; | 
|---|
| 1079 | case OLD_ARRAY_NORMAL: { | 
|---|
| 1080 | if (p_old_format & OLD_ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) { | 
|---|
| 1081 | if ((p_old_format & OLD_ARRAY_COMPRESS_NORMAL) && (p_old_format & OLD_ARRAY_FORMAT_TANGENT) && (p_old_format & OLD_ARRAY_COMPRESS_TANGENT)) { | 
|---|
| 1082 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1083 | const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1084 | int16_t *dst = (int16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; | 
|---|
| 1085 |  | 
|---|
| 1086 | dst[0] = (int16_t)CLAMP(src[0] / 127.0f * 32767, -32768, 32767); | 
|---|
| 1087 | dst[1] = (int16_t)CLAMP(src[1] / 127.0f * 32767, -32768, 32767); | 
|---|
| 1088 | } | 
|---|
| 1089 | src_offset += sizeof(int8_t) * 2; | 
|---|
| 1090 | } else { | 
|---|
| 1091 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1092 | const int16_t *src = (const int16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1093 | int16_t *dst = (int16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; | 
|---|
| 1094 |  | 
|---|
| 1095 | dst[0] = src[0]; | 
|---|
| 1096 | dst[1] = src[1]; | 
|---|
| 1097 | } | 
|---|
| 1098 | src_offset += sizeof(int16_t) * 2; | 
|---|
| 1099 | } | 
|---|
| 1100 | } else { // No Octahedral compression | 
|---|
| 1101 | if (p_old_format & OLD_ARRAY_COMPRESS_NORMAL) { | 
|---|
| 1102 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1103 | const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1104 | const Vector3 original_normal(src[0], src[1], src[2]); | 
|---|
| 1105 | Vector2 res = original_normal.octahedron_encode(); | 
|---|
| 1106 |  | 
|---|
| 1107 | uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; | 
|---|
| 1108 | dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); | 
|---|
| 1109 | dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); | 
|---|
| 1110 | } | 
|---|
| 1111 | src_offset += sizeof(uint8_t) * 4; // 1 byte padding | 
|---|
| 1112 | } else { | 
|---|
| 1113 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1114 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1115 | const Vector3 original_normal(src[0], src[1], src[2]); | 
|---|
| 1116 | Vector2 res = original_normal.octahedron_encode(); | 
|---|
| 1117 |  | 
|---|
| 1118 | uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; | 
|---|
| 1119 | dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); | 
|---|
| 1120 | dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); | 
|---|
| 1121 | } | 
|---|
| 1122 | src_offset += sizeof(float) * 3; | 
|---|
| 1123 | } | 
|---|
| 1124 | } | 
|---|
| 1125 |  | 
|---|
| 1126 | } break; | 
|---|
| 1127 | case OLD_ARRAY_TANGENT: { | 
|---|
| 1128 | if (p_old_format & OLD_ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) { | 
|---|
| 1129 | if (p_old_format & OLD_ARRAY_COMPRESS_TANGENT) { // int8 SNORM -> uint16 UNORM | 
|---|
| 1130 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1131 | const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1132 | uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; | 
|---|
| 1133 |  | 
|---|
| 1134 | dst[0] = (uint16_t)CLAMP((src[0] / 127.0f * .5f + .5f) * 65535, 0, 65535); | 
|---|
| 1135 | dst[1] = (uint16_t)CLAMP((src[1] / 127.0f * .5f + .5f) * 65535, 0, 65535); | 
|---|
| 1136 | } | 
|---|
| 1137 | src_offset += sizeof(uint8_t) * 2; | 
|---|
| 1138 | } else { // int16 SNORM -> uint16 UNORM | 
|---|
| 1139 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1140 | const int16_t *src = (const int16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1141 | uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; | 
|---|
| 1142 |  | 
|---|
| 1143 | dst[0] = (uint16_t)CLAMP((src[0] / 32767.0f * .5f + .5f) * 65535, 0, 65535); | 
|---|
| 1144 | dst[1] = (uint16_t)CLAMP((src[1] / 32767.0f * .5f + .5f) * 65535, 0, 65535); | 
|---|
| 1145 | } | 
|---|
| 1146 | src_offset += sizeof(uint16_t) * 2; | 
|---|
| 1147 | } | 
|---|
| 1148 | } else { // No Octahedral compression | 
|---|
| 1149 | if (p_old_format & OLD_ARRAY_COMPRESS_TANGENT) { | 
|---|
| 1150 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1151 | const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1152 | const Vector3 original_tangent(src[0], src[1], src[2]); | 
|---|
| 1153 | Vector2 res = original_tangent.octahedron_tangent_encode(src[3]); | 
|---|
| 1154 |  | 
|---|
| 1155 | uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; | 
|---|
| 1156 | dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); | 
|---|
| 1157 | dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); | 
|---|
| 1158 | } | 
|---|
| 1159 | src_offset += sizeof(uint8_t) * 4; | 
|---|
| 1160 | } else { | 
|---|
| 1161 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1162 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1163 | const Vector3 original_tangent(src[0], src[1], src[2]); | 
|---|
| 1164 | Vector2 res = original_tangent.octahedron_tangent_encode(src[3]); | 
|---|
| 1165 |  | 
|---|
| 1166 | uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; | 
|---|
| 1167 | dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); | 
|---|
| 1168 | dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); | 
|---|
| 1169 | } | 
|---|
| 1170 | src_offset += sizeof(float) * 4; | 
|---|
| 1171 | } | 
|---|
| 1172 | } | 
|---|
| 1173 | } break; | 
|---|
| 1174 | case OLD_ARRAY_COLOR: { | 
|---|
| 1175 | if (p_old_format & OLD_ARRAY_COMPRESS_COLOR) { | 
|---|
| 1176 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1177 | const uint32_t *src = (const uint32_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1178 | uint32_t *dst = (uint32_t *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_COLOR]]; | 
|---|
| 1179 |  | 
|---|
| 1180 | *dst = *src; | 
|---|
| 1181 | } | 
|---|
| 1182 | src_offset += sizeof(uint32_t); | 
|---|
| 1183 | } else { | 
|---|
| 1184 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1185 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1186 | uint8_t *dst = (uint8_t *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_COLOR]]; | 
|---|
| 1187 |  | 
|---|
| 1188 | dst[0] = uint8_t(CLAMP(src[0] * 255.0, 0.0, 255.0)); | 
|---|
| 1189 | dst[1] = uint8_t(CLAMP(src[1] * 255.0, 0.0, 255.0)); | 
|---|
| 1190 | dst[2] = uint8_t(CLAMP(src[2] * 255.0, 0.0, 255.0)); | 
|---|
| 1191 | dst[3] = uint8_t(CLAMP(src[3] * 255.0, 0.0, 255.0)); | 
|---|
| 1192 | } | 
|---|
| 1193 | src_offset += sizeof(float) * 4; | 
|---|
| 1194 | } | 
|---|
| 1195 | } break; | 
|---|
| 1196 | case OLD_ARRAY_TEX_UV: { | 
|---|
| 1197 | if (p_old_format & OLD_ARRAY_COMPRESS_TEX_UV) { | 
|---|
| 1198 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1199 | const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1200 | float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV]]; | 
|---|
| 1201 |  | 
|---|
| 1202 | dst[0] = Math::half_to_float(src[0]); | 
|---|
| 1203 | dst[1] = Math::half_to_float(src[1]); | 
|---|
| 1204 | } | 
|---|
| 1205 | src_offset += sizeof(uint16_t) * 2; | 
|---|
| 1206 | } else { | 
|---|
| 1207 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1208 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1209 | float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV]]; | 
|---|
| 1210 |  | 
|---|
| 1211 | dst[0] = src[0]; | 
|---|
| 1212 | dst[1] = src[1]; | 
|---|
| 1213 | } | 
|---|
| 1214 | src_offset += sizeof(float) * 2; | 
|---|
| 1215 | } | 
|---|
| 1216 |  | 
|---|
| 1217 | } break; | 
|---|
| 1218 | case OLD_ARRAY_TEX_UV2: { | 
|---|
| 1219 | if (p_old_format & OLD_ARRAY_COMPRESS_TEX_UV2) { | 
|---|
| 1220 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1221 | const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1222 | float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV2]]; | 
|---|
| 1223 |  | 
|---|
| 1224 | dst[0] = Math::half_to_float(src[0]); | 
|---|
| 1225 | dst[1] = Math::half_to_float(src[1]); | 
|---|
| 1226 | } | 
|---|
| 1227 | src_offset += sizeof(uint16_t) * 2; | 
|---|
| 1228 | } else { | 
|---|
| 1229 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1230 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1231 | float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV2]]; | 
|---|
| 1232 |  | 
|---|
| 1233 | dst[0] = src[0]; | 
|---|
| 1234 | dst[1] = src[1]; | 
|---|
| 1235 | } | 
|---|
| 1236 | src_offset += sizeof(float) * 2; | 
|---|
| 1237 | } | 
|---|
| 1238 | } break; | 
|---|
| 1239 | case OLD_ARRAY_BONES: { | 
|---|
| 1240 | if (p_old_format & OLD_ARRAY_FLAG_USE_16_BIT_BONES) { | 
|---|
| 1241 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1242 | const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1243 | uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_BONES]]; | 
|---|
| 1244 |  | 
|---|
| 1245 | dst[0] = src[0]; | 
|---|
| 1246 | dst[1] = src[1]; | 
|---|
| 1247 | dst[2] = src[2]; | 
|---|
| 1248 | dst[3] = src[3]; | 
|---|
| 1249 | } | 
|---|
| 1250 | src_offset += sizeof(uint16_t) * 4; | 
|---|
| 1251 | } else { | 
|---|
| 1252 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1253 | const uint8_t *src = (const uint8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1254 | uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_BONES]]; | 
|---|
| 1255 |  | 
|---|
| 1256 | dst[0] = src[0]; | 
|---|
| 1257 | dst[1] = src[1]; | 
|---|
| 1258 | dst[2] = src[2]; | 
|---|
| 1259 | dst[3] = src[3]; | 
|---|
| 1260 | } | 
|---|
| 1261 | src_offset += sizeof(uint8_t) * 4; | 
|---|
| 1262 | } | 
|---|
| 1263 | } break; | 
|---|
| 1264 | case OLD_ARRAY_WEIGHTS: { | 
|---|
| 1265 | if (p_old_format & OLD_ARRAY_COMPRESS_WEIGHTS) { | 
|---|
| 1266 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1267 | const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1268 | uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_WEIGHTS]]; | 
|---|
| 1269 |  | 
|---|
| 1270 | dst[0] = src[0]; | 
|---|
| 1271 | dst[1] = src[1]; | 
|---|
| 1272 | dst[2] = src[2]; | 
|---|
| 1273 | dst[3] = src[3]; | 
|---|
| 1274 | } | 
|---|
| 1275 | src_offset += sizeof(uint16_t) * 4; | 
|---|
| 1276 | } else { | 
|---|
| 1277 | for (uint32_t i = 0; i < p_elements; i++) { | 
|---|
| 1278 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; | 
|---|
| 1279 | uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_WEIGHTS]]; | 
|---|
| 1280 |  | 
|---|
| 1281 | dst[0] = uint16_t(CLAMP(src[0] * 65535.0, 0, 65535.0)); | 
|---|
| 1282 | dst[1] = uint16_t(CLAMP(src[1] * 65535.0, 0, 65535.0)); | 
|---|
| 1283 | dst[2] = uint16_t(CLAMP(src[2] * 65535.0, 0, 65535.0)); | 
|---|
| 1284 | dst[3] = uint16_t(CLAMP(src[3] * 65535.0, 0, 65535.0)); | 
|---|
| 1285 | } | 
|---|
| 1286 | src_offset += sizeof(float) * 4; | 
|---|
| 1287 | } | 
|---|
| 1288 | } break; | 
|---|
| 1289 | default: { | 
|---|
| 1290 | } | 
|---|
| 1291 | } | 
|---|
| 1292 | } | 
|---|
| 1293 | } | 
|---|
| 1294 |  | 
|---|
| 1295 | bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { | 
|---|
| 1296 | String sname = p_name; | 
|---|
| 1297 |  | 
|---|
| 1298 | if (sname.begins_with( "surface_")) { | 
|---|
| 1299 | int sl = sname.find( "/"); | 
|---|
| 1300 | if (sl == -1) { | 
|---|
| 1301 | return false; | 
|---|
| 1302 | } | 
|---|
| 1303 | int idx = sname.substr(8, sl - 8).to_int(); | 
|---|
| 1304 |  | 
|---|
| 1305 | String what = sname.get_slicec('/', 1); | 
|---|
| 1306 | if (what == "material") { | 
|---|
| 1307 | surface_set_material(idx, p_value); | 
|---|
| 1308 | } else if (what == "name") { | 
|---|
| 1309 | surface_set_name(idx, p_value); | 
|---|
| 1310 | } | 
|---|
| 1311 | return true; | 
|---|
| 1312 | } | 
|---|
| 1313 |  | 
|---|
| 1314 | #ifndef DISABLE_DEPRECATED | 
|---|
| 1315 | // Kept for compatibility from 3.x to 4.0. | 
|---|
| 1316 | if (!sname.begins_with( "surfaces")) { | 
|---|
| 1317 | return false; | 
|---|
| 1318 | } | 
|---|
| 1319 |  | 
|---|
| 1320 | WARN_DEPRECATED_MSG(vformat( | 
|---|
| 1321 | "Mesh uses old surface format, which is deprecated (and loads slower). Consider re-importing or re-saving the scene. Path: \"%s\"", | 
|---|
| 1322 | get_path())); | 
|---|
| 1323 |  | 
|---|
| 1324 | int idx = sname.get_slicec('/', 1).to_int(); | 
|---|
| 1325 | String what = sname.get_slicec('/', 2); | 
|---|
| 1326 |  | 
|---|
| 1327 | if (idx == surfaces.size()) { | 
|---|
| 1328 | //create | 
|---|
| 1329 | Dictionary d = p_value; | 
|---|
| 1330 | ERR_FAIL_COND_V(!d.has( "primitive"), false); | 
|---|
| 1331 |  | 
|---|
| 1332 | if (d.has( "arrays")) { | 
|---|
| 1333 | //oldest format (2.x) | 
|---|
| 1334 | ERR_FAIL_COND_V(!d.has( "morph_arrays"), false); | 
|---|
| 1335 | Array morph_arrays = d[ "morph_arrays"]; | 
|---|
| 1336 | for (int i = 0; i < morph_arrays.size(); i++) { | 
|---|
| 1337 | morph_arrays[i] = _convert_old_array(morph_arrays[i]); | 
|---|
| 1338 | } | 
|---|
| 1339 | add_surface_from_arrays(_old_primitives[int(d[ "primitive"])], _convert_old_array(d[ "arrays"]), morph_arrays); | 
|---|
| 1340 |  | 
|---|
| 1341 | } else if (d.has( "array_data")) { | 
|---|
| 1342 | //print_line("array data (old style"); | 
|---|
| 1343 | //older format (3.x) | 
|---|
| 1344 | Vector<uint8_t> array_data = d[ "array_data"]; | 
|---|
| 1345 | Vector<uint8_t> array_index_data; | 
|---|
| 1346 | if (d.has( "array_index_data")) { | 
|---|
| 1347 | array_index_data = d[ "array_index_data"]; | 
|---|
| 1348 | } | 
|---|
| 1349 |  | 
|---|
| 1350 | ERR_FAIL_COND_V(!d.has( "format"), false); | 
|---|
| 1351 | uint32_t old_format = d[ "format"]; | 
|---|
| 1352 |  | 
|---|
| 1353 | uint32_t primitive = d[ "primitive"]; | 
|---|
| 1354 |  | 
|---|
| 1355 | primitive = _old_primitives[primitive]; //compatibility | 
|---|
| 1356 |  | 
|---|
| 1357 | ERR_FAIL_COND_V(!d.has( "vertex_count"), false); | 
|---|
| 1358 | int vertex_count = d[ "vertex_count"]; | 
|---|
| 1359 |  | 
|---|
| 1360 | uint32_t new_format = ARRAY_FORMAT_VERTEX; | 
|---|
| 1361 |  | 
|---|
| 1362 | if (old_format & OLD_ARRAY_FORMAT_NORMAL) { | 
|---|
| 1363 | new_format |= ARRAY_FORMAT_NORMAL; | 
|---|
| 1364 | } | 
|---|
| 1365 | if (old_format & OLD_ARRAY_FORMAT_TANGENT) { | 
|---|
| 1366 | new_format |= ARRAY_FORMAT_TANGENT; | 
|---|
| 1367 | } | 
|---|
| 1368 | if (old_format & OLD_ARRAY_FORMAT_COLOR) { | 
|---|
| 1369 | new_format |= ARRAY_FORMAT_COLOR; | 
|---|
| 1370 | } | 
|---|
| 1371 | if (old_format & OLD_ARRAY_FORMAT_TEX_UV) { | 
|---|
| 1372 | new_format |= ARRAY_FORMAT_TEX_UV; | 
|---|
| 1373 | } | 
|---|
| 1374 | if (old_format & OLD_ARRAY_FORMAT_TEX_UV2) { | 
|---|
| 1375 | new_format |= ARRAY_FORMAT_TEX_UV2; | 
|---|
| 1376 | } | 
|---|
| 1377 | if (old_format & OLD_ARRAY_FORMAT_BONES) { | 
|---|
| 1378 | new_format |= ARRAY_FORMAT_BONES; | 
|---|
| 1379 | } | 
|---|
| 1380 | if (old_format & OLD_ARRAY_FORMAT_WEIGHTS) { | 
|---|
| 1381 | new_format |= ARRAY_FORMAT_WEIGHTS; | 
|---|
| 1382 | } | 
|---|
| 1383 | if (old_format & OLD_ARRAY_FORMAT_INDEX) { | 
|---|
| 1384 | new_format |= ARRAY_FORMAT_INDEX; | 
|---|
| 1385 | } | 
|---|
| 1386 | if (old_format & OLD_ARRAY_FLAG_USE_2D_VERTICES) { | 
|---|
| 1387 | new_format |= OLD_ARRAY_FLAG_USE_2D_VERTICES; | 
|---|
| 1388 | } | 
|---|
| 1389 |  | 
|---|
| 1390 | Vector<uint8_t> vertex_array; | 
|---|
| 1391 | Vector<uint8_t> attribute_array; | 
|---|
| 1392 | Vector<uint8_t> skin_array; | 
|---|
| 1393 |  | 
|---|
| 1394 | _fix_array_compatibility(array_data, old_format, new_format, vertex_count, vertex_array, attribute_array, skin_array); | 
|---|
| 1395 |  | 
|---|
| 1396 | int index_count = 0; | 
|---|
| 1397 | if (d.has( "index_count")) { | 
|---|
| 1398 | index_count = d[ "index_count"]; | 
|---|
| 1399 | } | 
|---|
| 1400 |  | 
|---|
| 1401 | Vector<uint8_t> blend_shapes_new; | 
|---|
| 1402 |  | 
|---|
| 1403 | if (d.has( "blend_shape_data")) { | 
|---|
| 1404 | Array blend_shape_data = d[ "blend_shape_data"]; | 
|---|
| 1405 | for (int i = 0; i < blend_shape_data.size(); i++) { | 
|---|
| 1406 | Vector<uint8_t> blend_vertex_array; | 
|---|
| 1407 | Vector<uint8_t> blend_attribute_array; | 
|---|
| 1408 | Vector<uint8_t> blend_skin_array; | 
|---|
| 1409 |  | 
|---|
| 1410 | Vector<uint8_t> shape = blend_shape_data[i]; | 
|---|
| 1411 | _fix_array_compatibility(shape, old_format, new_format, vertex_count, blend_vertex_array, blend_attribute_array, blend_skin_array); | 
|---|
| 1412 |  | 
|---|
| 1413 | blend_shapes_new.append_array(blend_vertex_array); | 
|---|
| 1414 | } | 
|---|
| 1415 | } | 
|---|
| 1416 |  | 
|---|
| 1417 | //clear unused flags | 
|---|
| 1418 | print_verbose( "Mesh format pre-conversion: "+ itos(old_format)); | 
|---|
| 1419 |  | 
|---|
| 1420 | print_verbose( "Mesh format post-conversion: "+ itos(new_format)); | 
|---|
| 1421 |  | 
|---|
| 1422 | ERR_FAIL_COND_V(!d.has( "aabb"), false); | 
|---|
| 1423 | AABB aabb_new = d[ "aabb"]; | 
|---|
| 1424 |  | 
|---|
| 1425 | Vector<AABB> bone_aabb; | 
|---|
| 1426 | if (d.has( "skeleton_aabb")) { | 
|---|
| 1427 | Array baabb = d[ "skeleton_aabb"]; | 
|---|
| 1428 | bone_aabb.resize(baabb.size()); | 
|---|
| 1429 |  | 
|---|
| 1430 | for (int i = 0; i < baabb.size(); i++) { | 
|---|
| 1431 | bone_aabb.write[i] = baabb[i]; | 
|---|
| 1432 | } | 
|---|
| 1433 | } | 
|---|
| 1434 |  | 
|---|
| 1435 | add_surface(new_format, PrimitiveType(primitive), vertex_array, attribute_array, skin_array, vertex_count, array_index_data, index_count, aabb_new, blend_shapes_new, bone_aabb); | 
|---|
| 1436 |  | 
|---|
| 1437 | } else { | 
|---|
| 1438 | ERR_FAIL_V(false); | 
|---|
| 1439 | } | 
|---|
| 1440 |  | 
|---|
| 1441 | if (d.has( "material")) { | 
|---|
| 1442 | surface_set_material(idx, d[ "material"]); | 
|---|
| 1443 | } | 
|---|
| 1444 | if (d.has( "name")) { | 
|---|
| 1445 | surface_set_name(idx, d[ "name"]); | 
|---|
| 1446 | } | 
|---|
| 1447 |  | 
|---|
| 1448 | return true; | 
|---|
| 1449 | } | 
|---|
| 1450 | #endif // DISABLE_DEPRECATED | 
|---|
| 1451 |  | 
|---|
| 1452 | return false; | 
|---|
| 1453 | } | 
|---|
| 1454 |  | 
|---|
| 1455 | void ArrayMesh::_set_blend_shape_names(const PackedStringArray &p_names) { | 
|---|
| 1456 | ERR_FAIL_COND(surfaces.size() > 0); | 
|---|
| 1457 |  | 
|---|
| 1458 | blend_shapes.resize(p_names.size()); | 
|---|
| 1459 | for (int i = 0; i < p_names.size(); i++) { | 
|---|
| 1460 | blend_shapes.write[i] = p_names[i]; | 
|---|
| 1461 | } | 
|---|
| 1462 |  | 
|---|
| 1463 | if (mesh.is_valid()) { | 
|---|
| 1464 | RS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size()); | 
|---|
| 1465 | } | 
|---|
| 1466 | } | 
|---|
| 1467 |  | 
|---|
| 1468 | PackedStringArray ArrayMesh::_get_blend_shape_names() const { | 
|---|
| 1469 | PackedStringArray sarr; | 
|---|
| 1470 | sarr.resize(blend_shapes.size()); | 
|---|
| 1471 | for (int i = 0; i < blend_shapes.size(); i++) { | 
|---|
| 1472 | sarr.write[i] = blend_shapes[i]; | 
|---|
| 1473 | } | 
|---|
| 1474 | return sarr; | 
|---|
| 1475 | } | 
|---|
| 1476 |  | 
|---|
| 1477 | Array ArrayMesh::_get_surfaces() const { | 
|---|
| 1478 | if (mesh.is_null()) { | 
|---|
| 1479 | return Array(); | 
|---|
| 1480 | } | 
|---|
| 1481 |  | 
|---|
| 1482 | Array ret; | 
|---|
| 1483 | for (int i = 0; i < surfaces.size(); i++) { | 
|---|
| 1484 | RenderingServer::SurfaceData surface = RS::get_singleton()->mesh_get_surface(mesh, i); | 
|---|
| 1485 | Dictionary data; | 
|---|
| 1486 | data[ "format"] = surface.format; | 
|---|
| 1487 | data[ "primitive"] = surface.primitive; | 
|---|
| 1488 | data[ "vertex_data"] = surface.vertex_data; | 
|---|
| 1489 | data[ "vertex_count"] = surface.vertex_count; | 
|---|
| 1490 | if (surface.skin_data.size()) { | 
|---|
| 1491 | data[ "skin_data"] = surface.skin_data; | 
|---|
| 1492 | } | 
|---|
| 1493 | if (surface.attribute_data.size()) { | 
|---|
| 1494 | data[ "attribute_data"] = surface.attribute_data; | 
|---|
| 1495 | } | 
|---|
| 1496 | data[ "aabb"] = surface.aabb; | 
|---|
| 1497 | if (surface.index_count) { | 
|---|
| 1498 | data[ "index_data"] = surface.index_data; | 
|---|
| 1499 | data[ "index_count"] = surface.index_count; | 
|---|
| 1500 | }; | 
|---|
| 1501 |  | 
|---|
| 1502 | Array lods; | 
|---|
| 1503 | for (int j = 0; j < surface.lods.size(); j++) { | 
|---|
| 1504 | lods.push_back(surface.lods[j].edge_length); | 
|---|
| 1505 | lods.push_back(surface.lods[j].index_data); | 
|---|
| 1506 | } | 
|---|
| 1507 |  | 
|---|
| 1508 | if (lods.size()) { | 
|---|
| 1509 | data[ "lods"] = lods; | 
|---|
| 1510 | } | 
|---|
| 1511 |  | 
|---|
| 1512 | Array bone_aabbs; | 
|---|
| 1513 | for (int j = 0; j < surface.bone_aabbs.size(); j++) { | 
|---|
| 1514 | bone_aabbs.push_back(surface.bone_aabbs[j]); | 
|---|
| 1515 | } | 
|---|
| 1516 | if (bone_aabbs.size()) { | 
|---|
| 1517 | data[ "bone_aabbs"] = bone_aabbs; | 
|---|
| 1518 | } | 
|---|
| 1519 |  | 
|---|
| 1520 | if (surface.blend_shape_data.size()) { | 
|---|
| 1521 | data[ "blend_shapes"] = surface.blend_shape_data; | 
|---|
| 1522 | } | 
|---|
| 1523 |  | 
|---|
| 1524 | if (surfaces[i].material.is_valid()) { | 
|---|
| 1525 | data[ "material"] = surfaces[i].material; | 
|---|
| 1526 | } | 
|---|
| 1527 |  | 
|---|
| 1528 | if (!surfaces[i].name.is_empty()) { | 
|---|
| 1529 | data[ "name"] = surfaces[i].name; | 
|---|
| 1530 | } | 
|---|
| 1531 |  | 
|---|
| 1532 | if (surfaces[i].is_2d) { | 
|---|
| 1533 | data[ "2d"] = true; | 
|---|
| 1534 | } | 
|---|
| 1535 |  | 
|---|
| 1536 | ret.push_back(data); | 
|---|
| 1537 | } | 
|---|
| 1538 |  | 
|---|
| 1539 | return ret; | 
|---|
| 1540 | } | 
|---|
| 1541 |  | 
|---|
| 1542 | void ArrayMesh::_create_if_empty() const { | 
|---|
| 1543 | if (!mesh.is_valid()) { | 
|---|
| 1544 | mesh = RS::get_singleton()->mesh_create(); | 
|---|
| 1545 | RS::get_singleton()->mesh_set_blend_shape_mode(mesh, (RS::BlendShapeMode)blend_shape_mode); | 
|---|
| 1546 | RS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size()); | 
|---|
| 1547 | } | 
|---|
| 1548 | } | 
|---|
| 1549 |  | 
|---|
| 1550 | void ArrayMesh::_set_surfaces(const Array &p_surfaces) { | 
|---|
| 1551 | Vector<RS::SurfaceData> surface_data; | 
|---|
| 1552 | Vector<Ref<Material>> surface_materials; | 
|---|
| 1553 | Vector<String> surface_names; | 
|---|
| 1554 | Vector<bool> surface_2d; | 
|---|
| 1555 |  | 
|---|
| 1556 | for (int i = 0; i < p_surfaces.size(); i++) { | 
|---|
| 1557 | RS::SurfaceData surface; | 
|---|
| 1558 | Dictionary d = p_surfaces[i]; | 
|---|
| 1559 | ERR_FAIL_COND(!d.has( "format")); | 
|---|
| 1560 | ERR_FAIL_COND(!d.has( "primitive")); | 
|---|
| 1561 | ERR_FAIL_COND(!d.has( "vertex_data")); | 
|---|
| 1562 | ERR_FAIL_COND(!d.has( "vertex_count")); | 
|---|
| 1563 | ERR_FAIL_COND(!d.has( "aabb")); | 
|---|
| 1564 | surface.format = d[ "format"]; | 
|---|
| 1565 | surface.primitive = RS::PrimitiveType(int(d[ "primitive"])); | 
|---|
| 1566 | surface.vertex_data = d[ "vertex_data"]; | 
|---|
| 1567 | surface.vertex_count = d[ "vertex_count"]; | 
|---|
| 1568 | if (d.has( "attribute_data")) { | 
|---|
| 1569 | surface.attribute_data = d[ "attribute_data"]; | 
|---|
| 1570 | } | 
|---|
| 1571 | if (d.has( "skin_data")) { | 
|---|
| 1572 | surface.skin_data = d[ "skin_data"]; | 
|---|
| 1573 | } | 
|---|
| 1574 | surface.aabb = d[ "aabb"]; | 
|---|
| 1575 |  | 
|---|
| 1576 | if (d.has( "index_data")) { | 
|---|
| 1577 | ERR_FAIL_COND(!d.has( "index_count")); | 
|---|
| 1578 | surface.index_data = d[ "index_data"]; | 
|---|
| 1579 | surface.index_count = d[ "index_count"]; | 
|---|
| 1580 | } | 
|---|
| 1581 |  | 
|---|
| 1582 | if (d.has( "lods")) { | 
|---|
| 1583 | Array lods = d[ "lods"]; | 
|---|
| 1584 | ERR_FAIL_COND(lods.size() & 1); //must be even | 
|---|
| 1585 | for (int j = 0; j < lods.size(); j += 2) { | 
|---|
| 1586 | RS::SurfaceData::LOD lod; | 
|---|
| 1587 | lod.edge_length = lods[j + 0]; | 
|---|
| 1588 | lod.index_data = lods[j + 1]; | 
|---|
| 1589 | surface.lods.push_back(lod); | 
|---|
| 1590 | } | 
|---|
| 1591 | } | 
|---|
| 1592 |  | 
|---|
| 1593 | if (d.has( "bone_aabbs")) { | 
|---|
| 1594 | Array bone_aabbs = d[ "bone_aabbs"]; | 
|---|
| 1595 | for (int j = 0; j < bone_aabbs.size(); j++) { | 
|---|
| 1596 | surface.bone_aabbs.push_back(bone_aabbs[j]); | 
|---|
| 1597 | } | 
|---|
| 1598 | } | 
|---|
| 1599 |  | 
|---|
| 1600 | if (d.has( "blend_shapes")) { | 
|---|
| 1601 | surface.blend_shape_data = d[ "blend_shapes"]; | 
|---|
| 1602 | } | 
|---|
| 1603 |  | 
|---|
| 1604 | Ref<Material> material; | 
|---|
| 1605 | if (d.has( "material")) { | 
|---|
| 1606 | material = d[ "material"]; | 
|---|
| 1607 | if (material.is_valid()) { | 
|---|
| 1608 | surface.material = material->get_rid(); | 
|---|
| 1609 | } | 
|---|
| 1610 | } | 
|---|
| 1611 |  | 
|---|
| 1612 | String surf_name; | 
|---|
| 1613 | if (d.has( "name")) { | 
|---|
| 1614 | surf_name = d[ "name"]; | 
|---|
| 1615 | } | 
|---|
| 1616 |  | 
|---|
| 1617 | bool _2d = false; | 
|---|
| 1618 | if (d.has( "2d")) { | 
|---|
| 1619 | _2d = d[ "2d"]; | 
|---|
| 1620 | } | 
|---|
| 1621 |  | 
|---|
| 1622 | surface_data.push_back(surface); | 
|---|
| 1623 | surface_materials.push_back(material); | 
|---|
| 1624 | surface_names.push_back(surf_name); | 
|---|
| 1625 | surface_2d.push_back(_2d); | 
|---|
| 1626 | } | 
|---|
| 1627 |  | 
|---|
| 1628 | if (mesh.is_valid()) { | 
|---|
| 1629 | //if mesh exists, it needs to be updated | 
|---|
| 1630 | RS::get_singleton()->mesh_clear(mesh); | 
|---|
| 1631 | for (int i = 0; i < surface_data.size(); i++) { | 
|---|
| 1632 | RS::get_singleton()->mesh_add_surface(mesh, surface_data[i]); | 
|---|
| 1633 | } | 
|---|
| 1634 | } else { | 
|---|
| 1635 | // if mesh does not exist (first time this is loaded, most likely), | 
|---|
| 1636 | // we can create it with a single call, which is a lot more efficient and thread friendly | 
|---|
| 1637 | mesh = RS::get_singleton()->mesh_create_from_surfaces(surface_data, blend_shapes.size()); | 
|---|
| 1638 | RS::get_singleton()->mesh_set_blend_shape_mode(mesh, (RS::BlendShapeMode)blend_shape_mode); | 
|---|
| 1639 | } | 
|---|
| 1640 |  | 
|---|
| 1641 | surfaces.clear(); | 
|---|
| 1642 |  | 
|---|
| 1643 | aabb = AABB(); | 
|---|
| 1644 | for (int i = 0; i < surface_data.size(); i++) { | 
|---|
| 1645 | Surface s; | 
|---|
| 1646 | s.aabb = surface_data[i].aabb; | 
|---|
| 1647 | if (i == 0) { | 
|---|
| 1648 | aabb = s.aabb; | 
|---|
| 1649 | } else { | 
|---|
| 1650 | aabb.merge_with(s.aabb); | 
|---|
| 1651 | } | 
|---|
| 1652 |  | 
|---|
| 1653 | s.material = surface_materials[i]; | 
|---|
| 1654 | s.is_2d = surface_2d[i]; | 
|---|
| 1655 | s.name = surface_names[i]; | 
|---|
| 1656 |  | 
|---|
| 1657 | s.format = surface_data[i].format; | 
|---|
| 1658 | s.primitive = PrimitiveType(surface_data[i].primitive); | 
|---|
| 1659 | s.array_length = surface_data[i].vertex_count; | 
|---|
| 1660 | s.index_array_length = surface_data[i].index_count; | 
|---|
| 1661 |  | 
|---|
| 1662 | surfaces.push_back(s); | 
|---|
| 1663 | } | 
|---|
| 1664 | } | 
|---|
| 1665 |  | 
|---|
| 1666 | bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const { | 
|---|
| 1667 | if (_is_generated()) { | 
|---|
| 1668 | return false; | 
|---|
| 1669 | } | 
|---|
| 1670 |  | 
|---|
| 1671 | String sname = p_name; | 
|---|
| 1672 | if (sname.begins_with( "surface_")) { | 
|---|
| 1673 | int sl = sname.find( "/"); | 
|---|
| 1674 | if (sl == -1) { | 
|---|
| 1675 | return false; | 
|---|
| 1676 | } | 
|---|
| 1677 | int idx = sname.substr(8, sl - 8).to_int(); | 
|---|
| 1678 | String what = sname.get_slicec('/', 1); | 
|---|
| 1679 | if (what == "material") { | 
|---|
| 1680 | r_ret = surface_get_material(idx); | 
|---|
| 1681 | } else if (what == "name") { | 
|---|
| 1682 | r_ret = surface_get_name(idx); | 
|---|
| 1683 | } | 
|---|
| 1684 | return true; | 
|---|
| 1685 | } | 
|---|
| 1686 |  | 
|---|
| 1687 | return true; | 
|---|
| 1688 | } | 
|---|
| 1689 |  | 
|---|
| 1690 | void ArrayMesh::reset_state() { | 
|---|
| 1691 | clear_surfaces(); | 
|---|
| 1692 | clear_blend_shapes(); | 
|---|
| 1693 |  | 
|---|
| 1694 | aabb = AABB(); | 
|---|
| 1695 | blend_shape_mode = BLEND_SHAPE_MODE_RELATIVE; | 
|---|
| 1696 | custom_aabb = AABB(); | 
|---|
| 1697 | } | 
|---|
| 1698 |  | 
|---|
| 1699 | void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const { | 
|---|
| 1700 | if (_is_generated()) { | 
|---|
| 1701 | return; | 
|---|
| 1702 | } | 
|---|
| 1703 |  | 
|---|
| 1704 | for (int i = 0; i < surfaces.size(); i++) { | 
|---|
| 1705 | p_list->push_back(PropertyInfo(Variant::STRING, "surface_"+ itos(i) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); | 
|---|
| 1706 | if (surfaces[i].is_2d) { | 
|---|
| 1707 | p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_"+ itos(i) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial,ShaderMaterial", PROPERTY_USAGE_EDITOR)); | 
|---|
| 1708 | } else { | 
|---|
| 1709 | p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_"+ itos(i) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_EDITOR)); | 
|---|
| 1710 | } | 
|---|
| 1711 | } | 
|---|
| 1712 | } | 
|---|
| 1713 |  | 
|---|
| 1714 | void ArrayMesh::_recompute_aabb() { | 
|---|
| 1715 | // regenerate AABB | 
|---|
| 1716 | aabb = AABB(); | 
|---|
| 1717 |  | 
|---|
| 1718 | for (int i = 0; i < surfaces.size(); i++) { | 
|---|
| 1719 | if (i == 0) { | 
|---|
| 1720 | aabb = surfaces[i].aabb; | 
|---|
| 1721 | } else { | 
|---|
| 1722 | aabb.merge_with(surfaces[i].aabb); | 
|---|
| 1723 | } | 
|---|
| 1724 | } | 
|---|
| 1725 | } | 
|---|
| 1726 |  | 
|---|
| 1727 | // TODO: Need to add binding to add_surface using future MeshSurfaceData object. | 
|---|
| 1728 | void ArrayMesh::add_surface(BitField<ArrayFormat> p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, const Vector<uint8_t> &p_attribute_array, const Vector<uint8_t> &p_skin_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<uint8_t> &p_blend_shape_data, const Vector<AABB> &p_bone_aabbs, const Vector<RS::SurfaceData::LOD> &p_lods) { | 
|---|
| 1729 | ERR_FAIL_COND(surfaces.size() == RS::MAX_MESH_SURFACES); | 
|---|
| 1730 | _create_if_empty(); | 
|---|
| 1731 |  | 
|---|
| 1732 | Surface s; | 
|---|
| 1733 | s.aabb = p_aabb; | 
|---|
| 1734 | s.is_2d = p_format & ARRAY_FLAG_USE_2D_VERTICES; | 
|---|
| 1735 | s.primitive = p_primitive; | 
|---|
| 1736 | s.array_length = p_vertex_count; | 
|---|
| 1737 | s.index_array_length = p_index_count; | 
|---|
| 1738 | s.format = p_format; | 
|---|
| 1739 |  | 
|---|
| 1740 | surfaces.push_back(s); | 
|---|
| 1741 | _recompute_aabb(); | 
|---|
| 1742 |  | 
|---|
| 1743 | RS::SurfaceData sd; | 
|---|
| 1744 | sd.format = p_format; | 
|---|
| 1745 | sd.primitive = RS::PrimitiveType(p_primitive); | 
|---|
| 1746 | sd.aabb = p_aabb; | 
|---|
| 1747 | sd.vertex_count = p_vertex_count; | 
|---|
| 1748 | sd.vertex_data = p_array; | 
|---|
| 1749 | sd.attribute_data = p_attribute_array; | 
|---|
| 1750 | sd.skin_data = p_skin_array; | 
|---|
| 1751 | sd.index_count = p_index_count; | 
|---|
| 1752 | sd.index_data = p_index_array; | 
|---|
| 1753 | sd.blend_shape_data = p_blend_shape_data; | 
|---|
| 1754 | sd.bone_aabbs = p_bone_aabbs; | 
|---|
| 1755 | sd.lods = p_lods; | 
|---|
| 1756 |  | 
|---|
| 1757 | RenderingServer::get_singleton()->mesh_add_surface(mesh, sd); | 
|---|
| 1758 |  | 
|---|
| 1759 | clear_cache(); | 
|---|
| 1760 | notify_property_list_changed(); | 
|---|
| 1761 | emit_changed(); | 
|---|
| 1762 | } | 
|---|
| 1763 |  | 
|---|
| 1764 | void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const TypedArray<Array> &p_blend_shapes, const Dictionary &p_lods, BitField<ArrayFormat> p_flags) { | 
|---|
| 1765 | ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size()); | 
|---|
| 1766 | ERR_FAIL_COND(p_arrays.size() != ARRAY_MAX); | 
|---|
| 1767 |  | 
|---|
| 1768 | RS::SurfaceData surface; | 
|---|
| 1769 |  | 
|---|
| 1770 | Error err = RS::get_singleton()->mesh_create_surface_data_from_arrays(&surface, (RenderingServer::PrimitiveType)p_primitive, p_arrays, p_blend_shapes, p_lods, p_flags); | 
|---|
| 1771 | ERR_FAIL_COND(err != OK); | 
|---|
| 1772 |  | 
|---|
| 1773 | /* Debug code. | 
|---|
| 1774 | print_line("format: " + itos(surface.format)); | 
|---|
| 1775 | print_line("aabb: " + surface.aabb); | 
|---|
| 1776 | print_line("array size: " + itos(surface.vertex_data.size())); | 
|---|
| 1777 | print_line("vertex count: " + itos(surface.vertex_count)); | 
|---|
| 1778 | print_line("index size: " + itos(surface.index_data.size())); | 
|---|
| 1779 | print_line("index count: " + itos(surface.index_count)); | 
|---|
| 1780 | print_line("primitive: " + itos(surface.primitive)); | 
|---|
| 1781 | */ | 
|---|
| 1782 |  | 
|---|
| 1783 | add_surface(surface.format, PrimitiveType(surface.primitive), surface.vertex_data, surface.attribute_data, surface.skin_data, surface.vertex_count, surface.index_data, surface.index_count, surface.aabb, surface.blend_shape_data, surface.bone_aabbs, surface.lods); | 
|---|
| 1784 | } | 
|---|
| 1785 |  | 
|---|
| 1786 | Array ArrayMesh::surface_get_arrays(int p_surface) const { | 
|---|
| 1787 | ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); | 
|---|
| 1788 | return RenderingServer::get_singleton()->mesh_surface_get_arrays(mesh, p_surface); | 
|---|
| 1789 | } | 
|---|
| 1790 |  | 
|---|
| 1791 | TypedArray<Array> ArrayMesh::surface_get_blend_shape_arrays(int p_surface) const { | 
|---|
| 1792 | ERR_FAIL_INDEX_V(p_surface, surfaces.size(), TypedArray<Array>()); | 
|---|
| 1793 | return RenderingServer::get_singleton()->mesh_surface_get_blend_shape_arrays(mesh, p_surface); | 
|---|
| 1794 | } | 
|---|
| 1795 |  | 
|---|
| 1796 | Dictionary ArrayMesh::surface_get_lods(int p_surface) const { | 
|---|
| 1797 | ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Dictionary()); | 
|---|
| 1798 | return RenderingServer::get_singleton()->mesh_surface_get_lods(mesh, p_surface); | 
|---|
| 1799 | } | 
|---|
| 1800 |  | 
|---|
| 1801 | int ArrayMesh::get_surface_count() const { | 
|---|
| 1802 | return surfaces.size(); | 
|---|
| 1803 | } | 
|---|
| 1804 |  | 
|---|
| 1805 | void ArrayMesh::add_blend_shape(const StringName &p_name) { | 
|---|
| 1806 | ERR_FAIL_COND_MSG(surfaces.size(), "Can't add a shape key count if surfaces are already created."); | 
|---|
| 1807 |  | 
|---|
| 1808 | StringName shape_name = p_name; | 
|---|
| 1809 |  | 
|---|
| 1810 | if (blend_shapes.has(shape_name)) { | 
|---|
| 1811 | int count = 2; | 
|---|
| 1812 | do { | 
|---|
| 1813 | shape_name = String(p_name) + " "+ itos(count); | 
|---|
| 1814 | count++; | 
|---|
| 1815 | } while (blend_shapes.has(shape_name)); | 
|---|
| 1816 | } | 
|---|
| 1817 |  | 
|---|
| 1818 | blend_shapes.push_back(shape_name); | 
|---|
| 1819 |  | 
|---|
| 1820 | if (mesh.is_valid()) { | 
|---|
| 1821 | RS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size()); | 
|---|
| 1822 | } | 
|---|
| 1823 | } | 
|---|
| 1824 |  | 
|---|
| 1825 | int ArrayMesh::get_blend_shape_count() const { | 
|---|
| 1826 | return blend_shapes.size(); | 
|---|
| 1827 | } | 
|---|
| 1828 |  | 
|---|
| 1829 | StringName ArrayMesh::get_blend_shape_name(int p_index) const { | 
|---|
| 1830 | ERR_FAIL_INDEX_V(p_index, blend_shapes.size(), StringName()); | 
|---|
| 1831 | return blend_shapes[p_index]; | 
|---|
| 1832 | } | 
|---|
| 1833 |  | 
|---|
| 1834 | void ArrayMesh::set_blend_shape_name(int p_index, const StringName &p_name) { | 
|---|
| 1835 | ERR_FAIL_INDEX(p_index, blend_shapes.size()); | 
|---|
| 1836 |  | 
|---|
| 1837 | StringName shape_name = p_name; | 
|---|
| 1838 | int found = blend_shapes.find(shape_name); | 
|---|
| 1839 | if (found != -1 && found != p_index) { | 
|---|
| 1840 | int count = 2; | 
|---|
| 1841 | do { | 
|---|
| 1842 | shape_name = String(p_name) + " "+ itos(count); | 
|---|
| 1843 | count++; | 
|---|
| 1844 | } while (blend_shapes.find(shape_name) != -1); | 
|---|
| 1845 | } | 
|---|
| 1846 |  | 
|---|
| 1847 | blend_shapes.write[p_index] = shape_name; | 
|---|
| 1848 | } | 
|---|
| 1849 |  | 
|---|
| 1850 | void ArrayMesh::clear_blend_shapes() { | 
|---|
| 1851 | ERR_FAIL_COND_MSG(surfaces.size(), "Can't set shape key count if surfaces are already created."); | 
|---|
| 1852 |  | 
|---|
| 1853 | blend_shapes.clear(); | 
|---|
| 1854 |  | 
|---|
| 1855 | if (mesh.is_valid()) { | 
|---|
| 1856 | RS::get_singleton()->mesh_set_blend_shape_count(mesh, 0); | 
|---|
| 1857 | } | 
|---|
| 1858 | } | 
|---|
| 1859 |  | 
|---|
| 1860 | void ArrayMesh::set_blend_shape_mode(BlendShapeMode p_mode) { | 
|---|
| 1861 | blend_shape_mode = p_mode; | 
|---|
| 1862 | if (mesh.is_valid()) { | 
|---|
| 1863 | RS::get_singleton()->mesh_set_blend_shape_mode(mesh, (RS::BlendShapeMode)p_mode); | 
|---|
| 1864 | } | 
|---|
| 1865 | } | 
|---|
| 1866 |  | 
|---|
| 1867 | ArrayMesh::BlendShapeMode ArrayMesh::get_blend_shape_mode() const { | 
|---|
| 1868 | return blend_shape_mode; | 
|---|
| 1869 | } | 
|---|
| 1870 |  | 
|---|
| 1871 | int ArrayMesh::surface_get_array_len(int p_idx) const { | 
|---|
| 1872 | ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); | 
|---|
| 1873 | return surfaces[p_idx].array_length; | 
|---|
| 1874 | } | 
|---|
| 1875 |  | 
|---|
| 1876 | int ArrayMesh::surface_get_array_index_len(int p_idx) const { | 
|---|
| 1877 | ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); | 
|---|
| 1878 | return surfaces[p_idx].index_array_length; | 
|---|
| 1879 | } | 
|---|
| 1880 |  | 
|---|
| 1881 | BitField<Mesh::ArrayFormat> ArrayMesh::surface_get_format(int p_idx) const { | 
|---|
| 1882 | ERR_FAIL_INDEX_V(p_idx, surfaces.size(), 0); | 
|---|
| 1883 | return surfaces[p_idx].format; | 
|---|
| 1884 | } | 
|---|
| 1885 |  | 
|---|
| 1886 | ArrayMesh::PrimitiveType ArrayMesh::surface_get_primitive_type(int p_idx) const { | 
|---|
| 1887 | ERR_FAIL_INDEX_V(p_idx, surfaces.size(), PRIMITIVE_LINES); | 
|---|
| 1888 | return surfaces[p_idx].primitive; | 
|---|
| 1889 | } | 
|---|
| 1890 |  | 
|---|
| 1891 | void ArrayMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) { | 
|---|
| 1892 | ERR_FAIL_INDEX(p_idx, surfaces.size()); | 
|---|
| 1893 | if (surfaces[p_idx].material == p_material) { | 
|---|
| 1894 | return; | 
|---|
| 1895 | } | 
|---|
| 1896 | surfaces.write[p_idx].material = p_material; | 
|---|
| 1897 | RenderingServer::get_singleton()->mesh_surface_set_material(mesh, p_idx, p_material.is_null() ? RID() : p_material->get_rid()); | 
|---|
| 1898 |  | 
|---|
| 1899 | emit_changed(); | 
|---|
| 1900 | } | 
|---|
| 1901 |  | 
|---|
| 1902 | int ArrayMesh::surface_find_by_name(const String &p_name) const { | 
|---|
| 1903 | for (int i = 0; i < surfaces.size(); i++) { | 
|---|
| 1904 | if (surfaces[i].name == p_name) { | 
|---|
| 1905 | return i; | 
|---|
| 1906 | } | 
|---|
| 1907 | } | 
|---|
| 1908 | return -1; | 
|---|
| 1909 | } | 
|---|
| 1910 |  | 
|---|
| 1911 | void ArrayMesh::surface_set_name(int p_idx, const String &p_name) { | 
|---|
| 1912 | ERR_FAIL_INDEX(p_idx, surfaces.size()); | 
|---|
| 1913 |  | 
|---|
| 1914 | surfaces.write[p_idx].name = p_name; | 
|---|
| 1915 | emit_changed(); | 
|---|
| 1916 | } | 
|---|
| 1917 |  | 
|---|
| 1918 | String ArrayMesh::surface_get_name(int p_idx) const { | 
|---|
| 1919 | ERR_FAIL_INDEX_V(p_idx, surfaces.size(), String()); | 
|---|
| 1920 | return surfaces[p_idx].name; | 
|---|
| 1921 | } | 
|---|
| 1922 |  | 
|---|
| 1923 | void ArrayMesh::surface_update_vertex_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) { | 
|---|
| 1924 | ERR_FAIL_INDEX(p_surface, surfaces.size()); | 
|---|
| 1925 | RS::get_singleton()->mesh_surface_update_vertex_region(mesh, p_surface, p_offset, p_data); | 
|---|
| 1926 | emit_changed(); | 
|---|
| 1927 | } | 
|---|
| 1928 |  | 
|---|
| 1929 | void ArrayMesh::surface_update_attribute_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) { | 
|---|
| 1930 | ERR_FAIL_INDEX(p_surface, surfaces.size()); | 
|---|
| 1931 | RS::get_singleton()->mesh_surface_update_attribute_region(mesh, p_surface, p_offset, p_data); | 
|---|
| 1932 | emit_changed(); | 
|---|
| 1933 | } | 
|---|
| 1934 |  | 
|---|
| 1935 | void ArrayMesh::surface_update_skin_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) { | 
|---|
| 1936 | ERR_FAIL_INDEX(p_surface, surfaces.size()); | 
|---|
| 1937 | RS::get_singleton()->mesh_surface_update_skin_region(mesh, p_surface, p_offset, p_data); | 
|---|
| 1938 | emit_changed(); | 
|---|
| 1939 | } | 
|---|
| 1940 |  | 
|---|
| 1941 | void ArrayMesh::surface_set_custom_aabb(int p_idx, const AABB &p_aabb) { | 
|---|
| 1942 | ERR_FAIL_INDEX(p_idx, surfaces.size()); | 
|---|
| 1943 | surfaces.write[p_idx].aabb = p_aabb; | 
|---|
| 1944 | // set custom aabb too? | 
|---|
| 1945 | emit_changed(); | 
|---|
| 1946 | } | 
|---|
| 1947 |  | 
|---|
| 1948 | Ref<Material> ArrayMesh::surface_get_material(int p_idx) const { | 
|---|
| 1949 | ERR_FAIL_INDEX_V(p_idx, surfaces.size(), Ref<Material>()); | 
|---|
| 1950 | return surfaces[p_idx].material; | 
|---|
| 1951 | } | 
|---|
| 1952 |  | 
|---|
| 1953 | RID ArrayMesh::get_rid() const { | 
|---|
| 1954 | _create_if_empty(); | 
|---|
| 1955 | return mesh; | 
|---|
| 1956 | } | 
|---|
| 1957 |  | 
|---|
| 1958 | AABB ArrayMesh::get_aabb() const { | 
|---|
| 1959 | return aabb; | 
|---|
| 1960 | } | 
|---|
| 1961 |  | 
|---|
| 1962 | void ArrayMesh::clear_surfaces() { | 
|---|
| 1963 | if (!mesh.is_valid()) { | 
|---|
| 1964 | return; | 
|---|
| 1965 | } | 
|---|
| 1966 | RS::get_singleton()->mesh_clear(mesh); | 
|---|
| 1967 | surfaces.clear(); | 
|---|
| 1968 | aabb = AABB(); | 
|---|
| 1969 | } | 
|---|
| 1970 |  | 
|---|
| 1971 | void ArrayMesh::set_custom_aabb(const AABB &p_custom) { | 
|---|
| 1972 | _create_if_empty(); | 
|---|
| 1973 | custom_aabb = p_custom; | 
|---|
| 1974 | RS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); | 
|---|
| 1975 | emit_changed(); | 
|---|
| 1976 | } | 
|---|
| 1977 |  | 
|---|
| 1978 | AABB ArrayMesh::get_custom_aabb() const { | 
|---|
| 1979 | return custom_aabb; | 
|---|
| 1980 | } | 
|---|
| 1981 |  | 
|---|
| 1982 | void ArrayMesh::regen_normal_maps() { | 
|---|
| 1983 | if (surfaces.size() == 0) { | 
|---|
| 1984 | return; | 
|---|
| 1985 | } | 
|---|
| 1986 | Vector<Ref<SurfaceTool>> surfs; | 
|---|
| 1987 | for (int i = 0; i < get_surface_count(); i++) { | 
|---|
| 1988 | Ref<SurfaceTool> st = memnew(SurfaceTool); | 
|---|
| 1989 | st->create_from(Ref<ArrayMesh>(this), i); | 
|---|
| 1990 | surfs.push_back(st); | 
|---|
| 1991 | } | 
|---|
| 1992 |  | 
|---|
| 1993 | clear_surfaces(); | 
|---|
| 1994 |  | 
|---|
| 1995 | for (int i = 0; i < surfs.size(); i++) { | 
|---|
| 1996 | surfs.write[i]->generate_tangents(); | 
|---|
| 1997 | surfs.write[i]->commit(Ref<ArrayMesh>(this)); | 
|---|
| 1998 | } | 
|---|
| 1999 | } | 
|---|
| 2000 |  | 
|---|
| 2001 | //dirty hack | 
|---|
| 2002 | bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, const uint8_t *p_cache_data, bool *r_use_cache, uint8_t **r_mesh_cache, int *r_mesh_cache_size, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) = nullptr; | 
|---|
| 2003 |  | 
|---|
| 2004 | struct ArrayMeshLightmapSurface { | 
|---|
| 2005 | Ref<Material> material; | 
|---|
| 2006 | LocalVector<SurfaceTool::Vertex> vertices; | 
|---|
| 2007 | Mesh::PrimitiveType primitive = Mesh::PrimitiveType::PRIMITIVE_MAX; | 
|---|
| 2008 | uint32_t format = 0; | 
|---|
| 2009 | }; | 
|---|
| 2010 |  | 
|---|
| 2011 | Error ArrayMesh::lightmap_unwrap(const Transform3D &p_base_transform, float p_texel_size) { | 
|---|
| 2012 | Vector<uint8_t> null_cache; | 
|---|
| 2013 | return lightmap_unwrap_cached(p_base_transform, p_texel_size, null_cache, null_cache, false); | 
|---|
| 2014 | } | 
|---|
| 2015 |  | 
|---|
| 2016 | Error ArrayMesh::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, bool p_generate_cache) { | 
|---|
| 2017 | ERR_FAIL_NULL_V(array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED); | 
|---|
| 2018 | ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes."); | 
|---|
| 2019 | ERR_FAIL_COND_V_MSG(p_texel_size <= 0.0f, ERR_PARAMETER_RANGE_ERROR, "Texel size must be greater than 0."); | 
|---|
| 2020 |  | 
|---|
| 2021 | LocalVector<float> vertices; | 
|---|
| 2022 | LocalVector<float> normals; | 
|---|
| 2023 | LocalVector<int> indices; | 
|---|
| 2024 | LocalVector<float> uv; | 
|---|
| 2025 | LocalVector<Pair<int, int>> uv_indices; | 
|---|
| 2026 |  | 
|---|
| 2027 | Vector<ArrayMeshLightmapSurface> lightmap_surfaces; | 
|---|
| 2028 |  | 
|---|
| 2029 | // Keep only the scale | 
|---|
| 2030 | Basis basis = p_base_transform.get_basis(); | 
|---|
| 2031 | Vector3 scale = Vector3(basis.get_column(0).length(), basis.get_column(1).length(), basis.get_column(2).length()); | 
|---|
| 2032 |  | 
|---|
| 2033 | Transform3D transform; | 
|---|
| 2034 | transform.scale(scale); | 
|---|
| 2035 |  | 
|---|
| 2036 | Basis normal_basis = transform.basis.inverse().transposed(); | 
|---|
| 2037 |  | 
|---|
| 2038 | for (int i = 0; i < get_surface_count(); i++) { | 
|---|
| 2039 | ArrayMeshLightmapSurface s; | 
|---|
| 2040 | s.primitive = surface_get_primitive_type(i); | 
|---|
| 2041 |  | 
|---|
| 2042 | ERR_FAIL_COND_V_MSG(s.primitive != Mesh::PRIMITIVE_TRIANGLES, ERR_UNAVAILABLE, "Only triangles are supported for lightmap unwrap."); | 
|---|
| 2043 | s.format = surface_get_format(i); | 
|---|
| 2044 | ERR_FAIL_COND_V_MSG(!(s.format & ARRAY_FORMAT_NORMAL), ERR_UNAVAILABLE, "Normals are required for lightmap unwrap."); | 
|---|
| 2045 |  | 
|---|
| 2046 | Array arrays = surface_get_arrays(i); | 
|---|
| 2047 | s.material = surface_get_material(i); | 
|---|
| 2048 | SurfaceTool::create_vertex_array_from_triangle_arrays(arrays, s.vertices, &s.format); | 
|---|
| 2049 |  | 
|---|
| 2050 | PackedVector3Array rvertices = arrays[Mesh::ARRAY_VERTEX]; | 
|---|
| 2051 | int vc = rvertices.size(); | 
|---|
| 2052 |  | 
|---|
| 2053 | PackedVector3Array rnormals = arrays[Mesh::ARRAY_NORMAL]; | 
|---|
| 2054 |  | 
|---|
| 2055 | int vertex_ofs = vertices.size() / 3; | 
|---|
| 2056 |  | 
|---|
| 2057 | vertices.resize((vertex_ofs + vc) * 3); | 
|---|
| 2058 | normals.resize((vertex_ofs + vc) * 3); | 
|---|
| 2059 | uv_indices.resize(vertex_ofs + vc); | 
|---|
| 2060 |  | 
|---|
| 2061 | for (int j = 0; j < vc; j++) { | 
|---|
| 2062 | Vector3 v = transform.xform(rvertices[j]); | 
|---|
| 2063 | Vector3 n = normal_basis.xform(rnormals[j]).normalized(); | 
|---|
| 2064 |  | 
|---|
| 2065 | vertices[(j + vertex_ofs) * 3 + 0] = v.x; | 
|---|
| 2066 | vertices[(j + vertex_ofs) * 3 + 1] = v.y; | 
|---|
| 2067 | vertices[(j + vertex_ofs) * 3 + 2] = v.z; | 
|---|
| 2068 | normals[(j + vertex_ofs) * 3 + 0] = n.x; | 
|---|
| 2069 | normals[(j + vertex_ofs) * 3 + 1] = n.y; | 
|---|
| 2070 | normals[(j + vertex_ofs) * 3 + 2] = n.z; | 
|---|
| 2071 | uv_indices[j + vertex_ofs] = Pair<int, int>(i, j); | 
|---|
| 2072 | } | 
|---|
| 2073 |  | 
|---|
| 2074 | PackedInt32Array rindices = arrays[Mesh::ARRAY_INDEX]; | 
|---|
| 2075 | int ic = rindices.size(); | 
|---|
| 2076 |  | 
|---|
| 2077 | float eps = 1.19209290e-7F; // Taken from xatlas.h | 
|---|
| 2078 | if (ic == 0) { | 
|---|
| 2079 | for (int j = 0; j < vc / 3; j++) { | 
|---|
| 2080 | Vector3 p0 = transform.xform(rvertices[j * 3 + 0]); | 
|---|
| 2081 | Vector3 p1 = transform.xform(rvertices[j * 3 + 1]); | 
|---|
| 2082 | Vector3 p2 = transform.xform(rvertices[j * 3 + 2]); | 
|---|
| 2083 |  | 
|---|
| 2084 | if ((p0 - p1).length_squared() < eps || (p1 - p2).length_squared() < eps || (p2 - p0).length_squared() < eps) { | 
|---|
| 2085 | continue; | 
|---|
| 2086 | } | 
|---|
| 2087 |  | 
|---|
| 2088 | indices.push_back(vertex_ofs + j * 3 + 0); | 
|---|
| 2089 | indices.push_back(vertex_ofs + j * 3 + 1); | 
|---|
| 2090 | indices.push_back(vertex_ofs + j * 3 + 2); | 
|---|
| 2091 | } | 
|---|
| 2092 |  | 
|---|
| 2093 | } else { | 
|---|
| 2094 | for (int j = 0; j < ic / 3; j++) { | 
|---|
| 2095 | Vector3 p0 = transform.xform(rvertices[rindices[j * 3 + 0]]); | 
|---|
| 2096 | Vector3 p1 = transform.xform(rvertices[rindices[j * 3 + 1]]); | 
|---|
| 2097 | Vector3 p2 = transform.xform(rvertices[rindices[j * 3 + 2]]); | 
|---|
| 2098 |  | 
|---|
| 2099 | if ((p0 - p1).length_squared() < eps || (p1 - p2).length_squared() < eps || (p2 - p0).length_squared() < eps) { | 
|---|
| 2100 | continue; | 
|---|
| 2101 | } | 
|---|
| 2102 |  | 
|---|
| 2103 | indices.push_back(vertex_ofs + rindices[j * 3 + 0]); | 
|---|
| 2104 | indices.push_back(vertex_ofs + rindices[j * 3 + 1]); | 
|---|
| 2105 | indices.push_back(vertex_ofs + rindices[j * 3 + 2]); | 
|---|
| 2106 | } | 
|---|
| 2107 | } | 
|---|
| 2108 |  | 
|---|
| 2109 | lightmap_surfaces.push_back(s); | 
|---|
| 2110 | } | 
|---|
| 2111 |  | 
|---|
| 2112 | //unwrap | 
|---|
| 2113 |  | 
|---|
| 2114 | bool use_cache = p_generate_cache; // Used to request cache generation and to know if cache was used | 
|---|
| 2115 | uint8_t *gen_cache; | 
|---|
| 2116 | int gen_cache_size; | 
|---|
| 2117 | float *gen_uvs; | 
|---|
| 2118 | int *gen_vertices; | 
|---|
| 2119 | int *gen_indices; | 
|---|
| 2120 | int gen_vertex_count; | 
|---|
| 2121 | int gen_index_count; | 
|---|
| 2122 | int size_x; | 
|---|
| 2123 | int size_y; | 
|---|
| 2124 |  | 
|---|
| 2125 | bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), indices.size(), p_src_cache.ptr(), &use_cache, &gen_cache, &gen_cache_size, &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y); | 
|---|
| 2126 |  | 
|---|
| 2127 | if (!ok) { | 
|---|
| 2128 | return ERR_CANT_CREATE; | 
|---|
| 2129 | } | 
|---|
| 2130 |  | 
|---|
| 2131 | clear_surfaces(); | 
|---|
| 2132 |  | 
|---|
| 2133 | //create surfacetools for each surface.. | 
|---|
| 2134 | LocalVector<Ref<SurfaceTool>> surfaces_tools; | 
|---|
| 2135 |  | 
|---|
| 2136 | for (int i = 0; i < lightmap_surfaces.size(); i++) { | 
|---|
| 2137 | Ref<SurfaceTool> st; | 
|---|
| 2138 | st.instantiate(); | 
|---|
| 2139 | st->begin(Mesh::PRIMITIVE_TRIANGLES); | 
|---|
| 2140 | st->set_material(lightmap_surfaces[i].material); | 
|---|
| 2141 | surfaces_tools.push_back(st); //stay there | 
|---|
| 2142 | } | 
|---|
| 2143 |  | 
|---|
| 2144 | print_verbose( "Mesh: Gen indices: "+ itos(gen_index_count)); | 
|---|
| 2145 |  | 
|---|
| 2146 | //go through all indices | 
|---|
| 2147 | for (int i = 0; i < gen_index_count; i += 3) { | 
|---|
| 2148 | ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], (int)uv_indices.size(), ERR_BUG); | 
|---|
| 2149 | ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], (int)uv_indices.size(), ERR_BUG); | 
|---|
| 2150 | ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], (int)uv_indices.size(), ERR_BUG); | 
|---|
| 2151 |  | 
|---|
| 2152 | ERR_FAIL_COND_V(uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 1]]].first || uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG); | 
|---|
| 2153 |  | 
|---|
| 2154 | int surface = uv_indices[gen_vertices[gen_indices[i + 0]]].first; | 
|---|
| 2155 |  | 
|---|
| 2156 | for (int j = 0; j < 3; j++) { | 
|---|
| 2157 | SurfaceTool::Vertex v = lightmap_surfaces[surface].vertices[uv_indices[gen_vertices[gen_indices[i + j]]].second]; | 
|---|
| 2158 |  | 
|---|
| 2159 | if (lightmap_surfaces[surface].format & ARRAY_FORMAT_COLOR) { | 
|---|
| 2160 | surfaces_tools[surface]->set_color(v.color); | 
|---|
| 2161 | } | 
|---|
| 2162 | if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TEX_UV) { | 
|---|
| 2163 | surfaces_tools[surface]->set_uv(v.uv); | 
|---|
| 2164 | } | 
|---|
| 2165 | if (lightmap_surfaces[surface].format & ARRAY_FORMAT_NORMAL) { | 
|---|
| 2166 | surfaces_tools[surface]->set_normal(v.normal); | 
|---|
| 2167 | } | 
|---|
| 2168 | if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TANGENT) { | 
|---|
| 2169 | Plane t; | 
|---|
| 2170 | t.normal = v.tangent; | 
|---|
| 2171 | t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1; | 
|---|
| 2172 | surfaces_tools[surface]->set_tangent(t); | 
|---|
| 2173 | } | 
|---|
| 2174 | if (lightmap_surfaces[surface].format & ARRAY_FORMAT_BONES) { | 
|---|
| 2175 | surfaces_tools[surface]->set_bones(v.bones); | 
|---|
| 2176 | } | 
|---|
| 2177 | if (lightmap_surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) { | 
|---|
| 2178 | surfaces_tools[surface]->set_weights(v.weights); | 
|---|
| 2179 | } | 
|---|
| 2180 |  | 
|---|
| 2181 | Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]); | 
|---|
| 2182 | surfaces_tools[surface]->set_uv2(uv2); | 
|---|
| 2183 |  | 
|---|
| 2184 | surfaces_tools[surface]->add_vertex(v.vertex); | 
|---|
| 2185 | } | 
|---|
| 2186 | } | 
|---|
| 2187 |  | 
|---|
| 2188 | //generate surfaces | 
|---|
| 2189 | for (unsigned int i = 0; i < surfaces_tools.size(); i++) { | 
|---|
| 2190 | surfaces_tools[i]->index(); | 
|---|
| 2191 | surfaces_tools[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), lightmap_surfaces[i].format); | 
|---|
| 2192 | } | 
|---|
| 2193 |  | 
|---|
| 2194 | set_lightmap_size_hint(Size2(size_x, size_y)); | 
|---|
| 2195 |  | 
|---|
| 2196 | if (gen_cache_size > 0) { | 
|---|
| 2197 | r_dst_cache.resize(gen_cache_size); | 
|---|
| 2198 | memcpy(r_dst_cache.ptrw(), gen_cache, gen_cache_size); | 
|---|
| 2199 | memfree(gen_cache); | 
|---|
| 2200 | } | 
|---|
| 2201 |  | 
|---|
| 2202 | if (!use_cache) { | 
|---|
| 2203 | // Cache was not used, free the buffers | 
|---|
| 2204 | memfree(gen_vertices); | 
|---|
| 2205 | memfree(gen_indices); | 
|---|
| 2206 | memfree(gen_uvs); | 
|---|
| 2207 | } | 
|---|
| 2208 |  | 
|---|
| 2209 | return OK; | 
|---|
| 2210 | } | 
|---|
| 2211 |  | 
|---|
| 2212 | void ArrayMesh::set_shadow_mesh(const Ref<ArrayMesh> &p_mesh) { | 
|---|
| 2213 | shadow_mesh = p_mesh; | 
|---|
| 2214 | if (shadow_mesh.is_valid()) { | 
|---|
| 2215 | RS::get_singleton()->mesh_set_shadow_mesh(mesh, shadow_mesh->get_rid()); | 
|---|
| 2216 | } else { | 
|---|
| 2217 | RS::get_singleton()->mesh_set_shadow_mesh(mesh, RID()); | 
|---|
| 2218 | } | 
|---|
| 2219 | } | 
|---|
| 2220 |  | 
|---|
| 2221 | Ref<ArrayMesh> ArrayMesh::get_shadow_mesh() const { | 
|---|
| 2222 | return shadow_mesh; | 
|---|
| 2223 | } | 
|---|
| 2224 |  | 
|---|
| 2225 | void ArrayMesh::_bind_methods() { | 
|---|
| 2226 | ClassDB::bind_method(D_METHOD( "add_blend_shape", "name"), &ArrayMesh::add_blend_shape); | 
|---|
| 2227 | ClassDB::bind_method(D_METHOD( "get_blend_shape_count"), &ArrayMesh::get_blend_shape_count); | 
|---|
| 2228 | ClassDB::bind_method(D_METHOD( "get_blend_shape_name", "index"), &ArrayMesh::get_blend_shape_name); | 
|---|
| 2229 | ClassDB::bind_method(D_METHOD( "set_blend_shape_name", "index", "name"), &ArrayMesh::set_blend_shape_name); | 
|---|
| 2230 | ClassDB::bind_method(D_METHOD( "clear_blend_shapes"), &ArrayMesh::clear_blend_shapes); | 
|---|
| 2231 | ClassDB::bind_method(D_METHOD( "set_blend_shape_mode", "mode"), &ArrayMesh::set_blend_shape_mode); | 
|---|
| 2232 | ClassDB::bind_method(D_METHOD( "get_blend_shape_mode"), &ArrayMesh::get_blend_shape_mode); | 
|---|
| 2233 |  | 
|---|
| 2234 | ClassDB::bind_method(D_METHOD( "add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "lods", "flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(0)); | 
|---|
| 2235 | ClassDB::bind_method(D_METHOD( "clear_surfaces"), &ArrayMesh::clear_surfaces); | 
|---|
| 2236 | ClassDB::bind_method(D_METHOD( "surface_update_vertex_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_vertex_region); | 
|---|
| 2237 | ClassDB::bind_method(D_METHOD( "surface_update_attribute_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_attribute_region); | 
|---|
| 2238 | ClassDB::bind_method(D_METHOD( "surface_update_skin_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_skin_region); | 
|---|
| 2239 | ClassDB::bind_method(D_METHOD( "surface_get_array_len", "surf_idx"), &ArrayMesh::surface_get_array_len); | 
|---|
| 2240 | ClassDB::bind_method(D_METHOD( "surface_get_array_index_len", "surf_idx"), &ArrayMesh::surface_get_array_index_len); | 
|---|
| 2241 | ClassDB::bind_method(D_METHOD( "surface_get_format", "surf_idx"), &ArrayMesh::surface_get_format); | 
|---|
| 2242 | ClassDB::bind_method(D_METHOD( "surface_get_primitive_type", "surf_idx"), &ArrayMesh::surface_get_primitive_type); | 
|---|
| 2243 | ClassDB::bind_method(D_METHOD( "surface_find_by_name", "name"), &ArrayMesh::surface_find_by_name); | 
|---|
| 2244 | ClassDB::bind_method(D_METHOD( "surface_set_name", "surf_idx", "name"), &ArrayMesh::surface_set_name); | 
|---|
| 2245 | ClassDB::bind_method(D_METHOD( "surface_get_name", "surf_idx"), &ArrayMesh::surface_get_name); | 
|---|
| 2246 | ClassDB::bind_method(D_METHOD( "create_trimesh_shape"), &ArrayMesh::create_trimesh_shape); | 
|---|
| 2247 | ClassDB::bind_method(D_METHOD( "create_convex_shape", "clean", "simplify"), &ArrayMesh::create_convex_shape, DEFVAL(true), DEFVAL(false)); | 
|---|
| 2248 | ClassDB::bind_method(D_METHOD( "create_outline", "margin"), &ArrayMesh::create_outline); | 
|---|
| 2249 | ClassDB::bind_method(D_METHOD( "regen_normal_maps"), &ArrayMesh::regen_normal_maps); | 
|---|
| 2250 | ClassDB::set_method_flags(get_class_static(), _scs_create( "regen_normal_maps"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); | 
|---|
| 2251 | ClassDB::bind_method(D_METHOD( "lightmap_unwrap", "transform", "texel_size"), &ArrayMesh::lightmap_unwrap); | 
|---|
| 2252 | ClassDB::set_method_flags(get_class_static(), _scs_create( "lightmap_unwrap"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); | 
|---|
| 2253 | ClassDB::bind_method(D_METHOD( "generate_triangle_mesh"), &ArrayMesh::generate_triangle_mesh); | 
|---|
| 2254 |  | 
|---|
| 2255 | ClassDB::bind_method(D_METHOD( "set_custom_aabb", "aabb"), &ArrayMesh::set_custom_aabb); | 
|---|
| 2256 | ClassDB::bind_method(D_METHOD( "get_custom_aabb"), &ArrayMesh::get_custom_aabb); | 
|---|
| 2257 |  | 
|---|
| 2258 | ClassDB::bind_method(D_METHOD( "set_shadow_mesh", "mesh"), &ArrayMesh::set_shadow_mesh); | 
|---|
| 2259 | ClassDB::bind_method(D_METHOD( "get_shadow_mesh"), &ArrayMesh::get_shadow_mesh); | 
|---|
| 2260 |  | 
|---|
| 2261 | ClassDB::bind_method(D_METHOD( "_set_blend_shape_names", "blend_shape_names"), &ArrayMesh::_set_blend_shape_names); | 
|---|
| 2262 | ClassDB::bind_method(D_METHOD( "_get_blend_shape_names"), &ArrayMesh::_get_blend_shape_names); | 
|---|
| 2263 |  | 
|---|
| 2264 | ClassDB::bind_method(D_METHOD( "_set_surfaces", "surfaces"), &ArrayMesh::_set_surfaces); | 
|---|
| 2265 | ClassDB::bind_method(D_METHOD( "_get_surfaces"), &ArrayMesh::_get_surfaces); | 
|---|
| 2266 |  | 
|---|
| 2267 | ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "_blend_shape_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_blend_shape_names", "_get_blend_shape_names"); | 
|---|
| 2268 | ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_surfaces", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_surfaces", "_get_surfaces"); | 
|---|
| 2269 | ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_shape_mode", PROPERTY_HINT_ENUM, "Normalized,Relative"), "set_blend_shape_mode", "get_blend_shape_mode"); | 
|---|
| 2270 | ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_custom_aabb", "get_custom_aabb"); | 
|---|
| 2271 | ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shadow_mesh", PROPERTY_HINT_RESOURCE_TYPE, "ArrayMesh"), "set_shadow_mesh", "get_shadow_mesh"); | 
|---|
| 2272 | } | 
|---|
| 2273 |  | 
|---|
| 2274 | void ArrayMesh::reload_from_file() { | 
|---|
| 2275 | RenderingServer::get_singleton()->mesh_clear(mesh); | 
|---|
| 2276 | surfaces.clear(); | 
|---|
| 2277 | clear_blend_shapes(); | 
|---|
| 2278 | clear_cache(); | 
|---|
| 2279 |  | 
|---|
| 2280 | Resource::reload_from_file(); | 
|---|
| 2281 |  | 
|---|
| 2282 | notify_property_list_changed(); | 
|---|
| 2283 | } | 
|---|
| 2284 |  | 
|---|
| 2285 | ArrayMesh::ArrayMesh() { | 
|---|
| 2286 | //mesh is now created on demand | 
|---|
| 2287 | //mesh = RenderingServer::get_singleton()->mesh_create(); | 
|---|
| 2288 | } | 
|---|
| 2289 |  | 
|---|
| 2290 | ArrayMesh::~ArrayMesh() { | 
|---|
| 2291 | if (mesh.is_valid()) { | 
|---|
| 2292 | ERR_FAIL_NULL(RenderingServer::get_singleton()); | 
|---|
| 2293 | RenderingServer::get_singleton()->free(mesh); | 
|---|
| 2294 | } | 
|---|
| 2295 | } | 
|---|
| 2296 | /////////////// | 
|---|
| 2297 |  | 
|---|
| 2298 | void PlaceholderMesh::_bind_methods() { | 
|---|
| 2299 | ClassDB::bind_method(D_METHOD( "set_aabb", "aabb"), &PlaceholderMesh::set_aabb); | 
|---|
| 2300 | ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_aabb", "get_aabb"); | 
|---|
| 2301 | } | 
|---|
| 2302 |  | 
|---|
| 2303 | PlaceholderMesh::PlaceholderMesh() { | 
|---|
| 2304 | rid = RS::get_singleton()->mesh_create(); | 
|---|
| 2305 | } | 
|---|
| 2306 |  | 
|---|
| 2307 | PlaceholderMesh::~PlaceholderMesh() { | 
|---|
| 2308 | ERR_FAIL_NULL(RenderingServer::get_singleton()); | 
|---|
| 2309 | RS::get_singleton()->free(rid); | 
|---|
| 2310 | } | 
|---|
| 2311 |  | 
|---|