From 03b896c992fe0c488f361ce6106b32c43d9aae75 Mon Sep 17 00:00:00 2001 From: Lyuma Date: Sat, 11 Jun 2022 16:15:44 -0700 Subject: [PATCH] `SurfaceTool.set_custom_format` Fixes and documentation. Fix mistake making `set_custom_format` impossible to use. Automatically forward custom flags in `SurfaceTool.commit`. Add documentation in `SurfaceTool` and `Mesh` for custom channels. Deprecate `SurfaceTool.generate_lod` and expose `ImporterMesh.generate_lods`. --- doc/classes/ImporterMesh.xml | 10 +++++ doc/classes/Mesh.xml | 27 +++++++++++++ doc/classes/SurfaceTool.xml | 49 ++++++++++++++++++------ scene/resources/importer_mesh.cpp | 3 +- scene/resources/surface_tool.cpp | 63 +++++++++++++++++-------------- scene/resources/surface_tool.h | 12 +++--- 6 files changed, 117 insertions(+), 47 deletions(-) diff --git a/doc/classes/ImporterMesh.xml b/doc/classes/ImporterMesh.xml index 90e7df44217..00601cec752 100644 --- a/doc/classes/ImporterMesh.xml +++ b/doc/classes/ImporterMesh.xml @@ -39,6 +39,16 @@ Removes all surfaces and blend shapes from this [ImporterMesh]. + + + + + + Generates all lods for this ImporterMesh. + [code]normal_merge_angle[/code] and [code]normal_split_angle[/code] are in degrees and used in the same way as the importer settings in [code]lods[/code]. As a good default, use 25 and 60 respectively. + The number of generated lods can be accessed using [method get_surface_lod_count], and each LOD is available in [method get_surface_lod_size] and [method get_surface_lod_indices]. + + diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml index eeb6af24c9d..48fa2754d51 100644 --- a/doc/classes/Mesh.xml +++ b/doc/classes/Mesh.xml @@ -215,12 +215,16 @@ [PackedVector2Array] for second UV coordinates. + Contains custom color channel 0. [PackedByteArray] if [code](format >> [constant ARRAY_FORMAT_CUSTOM0_SHIFT]) & [constant ARRAY_FORMAT_CUSTOM_MASK])[/code] is [constant ARRAY_CUSTOM_RGBA8_UNORM], [constant ARRAY_CUSTOM_RGBA8_UNORM], [constant ARRAY_CUSTOM_RG_HALF] or [constant ARRAY_CUSTOM_RGBA_HALF]. [PackedFloat32Array] otherwise. + Contains custom color channel 1. [PackedByteArray] if [code](format >> [constant ARRAY_FORMAT_CUSTOM1_SHIFT]) & [constant ARRAY_FORMAT_CUSTOM_MASK])[/code] is [constant ARRAY_CUSTOM_RGBA8_UNORM], [constant ARRAY_CUSTOM_RGBA8_UNORM], [constant ARRAY_CUSTOM_RG_HALF] or [constant ARRAY_CUSTOM_RGBA_HALF]. [PackedFloat32Array] otherwise. + Contains custom color channel 2. [PackedByteArray] if [code](format >> [constant ARRAY_FORMAT_CUSTOM2_SHIFT]) & [constant ARRAY_FORMAT_CUSTOM_MASK])[/code] is [constant ARRAY_CUSTOM_RGBA8_UNORM], [constant ARRAY_CUSTOM_RGBA8_UNORM], [constant ARRAY_CUSTOM_RG_HALF] or [constant ARRAY_CUSTOM_RGBA_HALF]. [PackedFloat32Array] otherwise. + Contains custom color channel 3. [PackedByteArray] if [code](format >> [constant ARRAY_FORMAT_CUSTOM3_SHIFT]) & [constant ARRAY_FORMAT_CUSTOM_MASK])[/code] is [constant ARRAY_CUSTOM_RGBA8_UNORM], [constant ARRAY_CUSTOM_RGBA8_UNORM], [constant ARRAY_CUSTOM_RG_HALF] or [constant ARRAY_CUSTOM_RGBA_HALF]. [PackedFloat32Array] otherwise. [PackedFloat32Array] or [PackedInt32Array] of bone indices. Each element is a group of 4 numbers. @@ -236,20 +240,28 @@ Represents the size of the [enum ArrayType] enum. + Indicates this custom channel contains unsigned normalized byte colors from 0 to 1, encoded as [PackedByteArray]. + Indicates this custom channel contains signed normalized byte colors from -1 to 1, encoded as [PackedByteArray]. + Indicates this custom channel contains half precision float colors, encoded as [PackedByteArray]. Only red and green channels are used. + Indicates this custom channel contains half precision float colors, encoded as [PackedByteArray]. + Indicates this custom channel contains full float colors, in a [PackedFloat32Array]. Only the red green channel is used. + Indicates this custom channel contains full float colors, in a [PackedFloat32Array]. Only red and green channels are used. + Indicates this custom channel contains full float colors, in a [PackedFloat32Array]. Only red, green and blue channels are used. + Indicates this custom channel contains full float colors, in a [PackedFloat32Array]. Represents the size of the [enum ArrayCustomFormat] enum. @@ -273,12 +285,16 @@ Mesh array contains second UV. + Mesh array contains custom channel index 0. + Mesh array contains custom channel index 1. + Mesh array contains custom channel index 2. + Mesh array contains custom channel index 3. Mesh array contains bones. @@ -290,29 +306,40 @@ Mesh array uses indices. + Mask of mesh channels permitted in blend shapes. + Shift of first custom channel. + Number of format bits per custom channel. See [enum ArrayCustomFormat]. + Amount to shift [enum ArrayCustomFormat] for custom channel index 0. + Amount to shift [enum ArrayCustomFormat] for custom channel index 1. + Amount to shift [enum ArrayCustomFormat] for custom channel index 2. + Amount to shift [enum ArrayCustomFormat] for custom channel index 3. + Mask of custom format bits per custom channel. Must be shifted by one of the SHIFT constants. See [enum ArrayCustomFormat]. + Shift of first compress flag. Compress flags should be passed to [method ArrayMesh.add_surface_from_arrays] and [method SurfaceTool.commit]. Flag used to mark that the array contains 2D vertices. + Flag indices that the mesh data will use [code]GL_DYNAMIC_DRAW[/code] on GLES. Unused on Vulkan. + Flag used to mark that the mesh contains up to 8 bone influences per vertex. This flag indicates that [constant ARRAY_BONES] and [constant ARRAY_WEIGHTS] elements will have double length. Blend shapes are normalized. diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml index 43d34d3890c..ad638a680b6 100644 --- a/doc/classes/SurfaceTool.xml +++ b/doc/classes/SurfaceTool.xml @@ -35,7 +35,7 @@ - Adds an index to index array if you are using indexed vertices. Does not need to be called before adding vertices. + Adds a vertex to index array if you are using indexed vertices. Does not need to be called before adding vertices. @@ -123,6 +123,8 @@ + Generates a LOD for a given [code]nd_threshold[/code] in linear units (square root of quadric error metric), using at most [code]target_index_count[/code] indices. + Deprecated. Unused internally and neglects to preserve normals or UVs. Consider using [method ImporterMesh.generate_lods] instead. @@ -139,25 +141,31 @@ Generates a tangent vector for each vertex. Requires that each vertex have UVs and normals set already (see [method generate_normals]). + + + + Returns the axis-aligned bounding box of the vertex positions. + + - + + Returns the format for custom [code]channel_index[/code] (currently up to 4). Returns [constant CUSTOM_MAX] if this custom channel is unused. - - - - - - + + Returns the type of mesh geometry, such as [constant Mesh.PRIMITIVE_TRIANGLES]. + By default, returns [constant SKIN_4_WEIGHTS] to indicate only 4 bone influences per vertex are used. + Returns [constant SKIN_8_WEIGHTS] if up to 8 influences are used. + [b]Note:[/b] This function returns an enum, not the exact number of weights. @@ -169,6 +177,7 @@ + Optimizes triangle sorting for performance. Requires that [method get_primitive_type] is [constant Mesh.PRIMITIVE_TRIANGLES]. @@ -188,16 +197,20 @@ - - + + + Sets the custom value on this vertex for [code]channel_index[/code]. + [method set_custom_format] must be called first for this [code]channel_index[/code]. Formats which are not RGBA will ignore other color channels. - + + Sets the color format for this custom [code]channel_index[/code]. Use [constant CUSTOM_MAX] to disable. + Must be invoked after [method begin] and should be set before [method commit] or [method commit_to_arrays]. @@ -218,6 +231,9 @@ + Set to [constant SKIN_8_WEIGHTS] to indicate that up to 8 bone influences per vertex may be used. + By default, only 4 bone influences are used ([constant SKIN_4_WEIGHTS]) + [b]Note:[/b] This function takes an enum, not the exact number of weights. @@ -258,26 +274,37 @@ + Limits range of data passed to `set_custom` to unsigned normalized 0 to 1 stored in 8 bits per channel. See [constant Mesh.ARRAY_CUSTOM_RGBA8_UNORM]. + Limits range of data passed to `set_custom` to signed normalized -1 to 1 stored in 8 bits per channel. See [constant Mesh.ARRAY_CUSTOM_RGBA8_SNORM]. + Stores data passed to `set_custom` as half precision floats, and uses only red and green color channels. See [constant Mesh.ARRAY_CUSTOM_RG_HALF]. + Stores data passed to `set_custom` as half precision floats and uses all color channels. See [constant Mesh.ARRAY_CUSTOM_RGBA_HALF]. + Stores data passed to `set_custom` as full precision floats, and uses only red color channel. See [constant Mesh.ARRAY_CUSTOM_R_FLOAT]. + Stores data passed to `set_custom` as full precision floats, and uses only red and green color channels. See [constant Mesh.ARRAY_CUSTOM_RG_FLOAT]. + Stores data passed to `set_custom` as full precision floats, and uses only red, green and blue color channels. See [constant Mesh.ARRAY_CUSTOM_RGB_FLOAT]. + Stores data passed to `set_custom` as full precision floats, and uses all color channels. See [constant Mesh.ARRAY_CUSTOM_RGBA_FLOAT]. + Used to indicate a disabled custom channel. + Each individual vertex can be influenced by only 4 bone weights. + Each individual vertex can be influenced by up to 8 bone weights. diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp index 0fbd29b1a61..71640357b95 100644 --- a/scene/resources/importer_mesh.cpp +++ b/scene/resources/importer_mesh.cpp @@ -1185,7 +1185,7 @@ Error ImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, for (unsigned int i = 0; i < surfaces_tools.size(); i++) { surfaces_tools[i]->index(); Array arrays = surfaces_tools[i]->commit_to_arrays(); - add_surface(surfaces_tools[i]->get_primitive(), arrays, Array(), Dictionary(), surfaces_tools[i]->get_material(), surfaces_tools[i]->get_meta("name")); + add_surface(surfaces_tools[i]->get_primitive_type(), arrays, Array(), Dictionary(), surfaces_tools[i]->get_material(), surfaces_tools[i]->get_meta("name")); } set_lightmap_size_hint(Size2(size_x, size_y)); @@ -1238,6 +1238,7 @@ void ImporterMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_surface_name", "surface_idx", "name"), &ImporterMesh::set_surface_name); ClassDB::bind_method(D_METHOD("set_surface_material", "surface_idx", "material"), &ImporterMesh::set_surface_material); + ClassDB::bind_method(D_METHOD("generate_lods", "normal_merge_angle", "normal_split_angle"), &ImporterMesh::generate_lods); ClassDB::bind_method(D_METHOD("get_mesh", "base_mesh"), &ImporterMesh::get_mesh, DEFVAL(Ref())); ClassDB::bind_method(D_METHOD("clear"), &ImporterMesh::clear); diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 0e41eed5701..77d6e3c6f93 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -315,19 +315,17 @@ void SurfaceTool::set_uv2(const Vector2 &p_uv2) { last_uv2 = p_uv2; } -void SurfaceTool::set_custom(int p_index, const Color &p_custom) { - ERR_FAIL_INDEX(p_index, RS::ARRAY_CUSTOM_COUNT); +void SurfaceTool::set_custom(int p_channel_index, const Color &p_custom) { + ERR_FAIL_INDEX(p_channel_index, RS::ARRAY_CUSTOM_COUNT); ERR_FAIL_COND(!begun); - ERR_FAIL_COND(last_custom_format[p_index] == CUSTOM_MAX); + ERR_FAIL_COND(last_custom_format[p_channel_index] == CUSTOM_MAX); static const uint32_t mask[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0, Mesh::ARRAY_FORMAT_CUSTOM1, Mesh::ARRAY_FORMAT_CUSTOM2, Mesh::ARRAY_FORMAT_CUSTOM3 }; - static const uint32_t shift[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM1_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM2_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM3_SHIFT }; - ERR_FAIL_COND(!first && !(format & mask[p_index])); + ERR_FAIL_COND(!first && !(format & mask[p_channel_index])); if (first) { - format |= mask[p_index]; - format |= last_custom_format[p_index] << shift[p_index]; + format |= mask[p_channel_index]; } - last_custom[p_index] = p_custom; + last_custom[p_channel_index] = p_custom; } void SurfaceTool::set_bones(const Vector &p_bones) { @@ -689,7 +687,7 @@ Array SurfaceTool::commit_to_arrays() { return a; } -Ref SurfaceTool::commit(const Ref &p_existing, uint32_t p_flags) { +Ref SurfaceTool::commit(const Ref &p_existing, uint32_t p_compress_flags) { Ref mesh; if (p_existing.is_valid()) { mesh = p_existing; @@ -707,7 +705,15 @@ Ref SurfaceTool::commit(const Ref &p_existing, uint32_t p_ Array a = commit_to_arrays(); - mesh->add_surface_from_arrays(primitive, a, Array(), Dictionary(), p_flags); + uint32_t compress_flags = (p_compress_flags >> RS::ARRAY_COMPRESS_FLAGS_BASE) << RS::ARRAY_COMPRESS_FLAGS_BASE; + static const uint32_t shift[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM1_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM2_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM3_SHIFT }; + for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) { + if (last_custom_format[i] != CUSTOM_MAX) { + compress_flags |= last_custom_format[i] << shift[i]; + } + } + + mesh->add_surface_from_arrays(primitive, a, Array(), Dictionary(), compress_flags); if (material.is_valid()) { mesh->surface_set_material(surface, material); @@ -988,9 +994,6 @@ void SurfaceTool::append_from(const Ref &p_existing, int p_surface, const for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) { if (format & custom_mask[j]) { CustomFormat new_format = (CustomFormat)((format >> custom_shift[j]) & RS::ARRAY_FORMAT_CUSTOM_MASK); - if (last_custom_format[j] != CUSTOM_MAX && last_custom_format[j] != new_format) { - WARN_PRINT(vformat("Custom %d format %d mismatch when appending format %d", j, last_custom_format[j], new_format)); - } last_custom_format[j] = new_format; } } @@ -1220,22 +1223,24 @@ SurfaceTool::SkinWeightCount SurfaceTool::get_skin_weight_count() const { return skin_weights; } -void SurfaceTool::set_custom_format(int p_index, CustomFormat p_format) { - ERR_FAIL_INDEX(p_index, RS::ARRAY_CUSTOM_COUNT); - ERR_FAIL_COND(begun); - last_custom_format[p_index] = p_format; +void SurfaceTool::set_custom_format(int p_channel_index, CustomFormat p_format) { + ERR_FAIL_INDEX(p_channel_index, RS::ARRAY_CUSTOM_COUNT); + ERR_FAIL_COND(!begun); + ERR_FAIL_INDEX(p_format, CUSTOM_MAX + 1); + last_custom_format[p_channel_index] = p_format; } -Mesh::PrimitiveType SurfaceTool::get_primitive() const { +Mesh::PrimitiveType SurfaceTool::get_primitive_type() const { return primitive; } -SurfaceTool::CustomFormat SurfaceTool::get_custom_format(int p_index) const { - ERR_FAIL_INDEX_V(p_index, RS::ARRAY_CUSTOM_COUNT, CUSTOM_MAX); - return last_custom_format[p_index]; +SurfaceTool::CustomFormat SurfaceTool::get_custom_format(int p_channel_index) const { + ERR_FAIL_INDEX_V(p_channel_index, RS::ARRAY_CUSTOM_COUNT, CUSTOM_MAX); + return last_custom_format[p_channel_index]; } void SurfaceTool::optimize_indices_for_cache() { ERR_FAIL_COND(optimize_vertex_cache_func == nullptr); ERR_FAIL_COND(index_array.size() == 0); + ERR_FAIL_COND(primitive != Mesh::PRIMITIVE_TRIANGLES); ERR_FAIL_COND(index_array.size() % 3 != 0); LocalVector old_index_array = index_array; @@ -1243,8 +1248,8 @@ void SurfaceTool::optimize_indices_for_cache() { optimize_vertex_cache_func((unsigned int *)index_array.ptr(), (unsigned int *)old_index_array.ptr(), old_index_array.size(), vertex_array.size()); } -float SurfaceTool::get_max_axis_length() const { - ERR_FAIL_COND_V(vertex_array.size() == 0, 0); +AABB SurfaceTool::get_aabb() const { + ERR_FAIL_COND_V(vertex_array.size() == 0, AABB()); AABB aabb; for (uint32_t i = 0; i < vertex_array.size(); i++) { @@ -1255,7 +1260,7 @@ float SurfaceTool::get_max_axis_length() const { } } - return aabb.get_longest_axis_size(); + return aabb; } Vector SurfaceTool::generate_lod(float p_threshold, int p_target_index_count) { Vector lod; @@ -1288,8 +1293,8 @@ void SurfaceTool::_bind_methods() { ClassDB::bind_method(D_METHOD("set_skin_weight_count", "count"), &SurfaceTool::set_skin_weight_count); ClassDB::bind_method(D_METHOD("get_skin_weight_count"), &SurfaceTool::get_skin_weight_count); - ClassDB::bind_method(D_METHOD("set_custom_format", "index", "format"), &SurfaceTool::set_custom_format); - ClassDB::bind_method(D_METHOD("get_custom_format", "index"), &SurfaceTool::get_custom_format); + ClassDB::bind_method(D_METHOD("set_custom_format", "channel_index", "format"), &SurfaceTool::set_custom_format); + ClassDB::bind_method(D_METHOD("get_custom_format", "channel_index"), &SurfaceTool::get_custom_format); ClassDB::bind_method(D_METHOD("begin", "primitive"), &SurfaceTool::begin); @@ -1301,7 +1306,7 @@ void SurfaceTool::_bind_methods() { ClassDB::bind_method(D_METHOD("set_uv2", "uv2"), &SurfaceTool::set_uv2); ClassDB::bind_method(D_METHOD("set_bones", "bones"), &SurfaceTool::set_bones); ClassDB::bind_method(D_METHOD("set_weights", "weights"), &SurfaceTool::set_weights); - ClassDB::bind_method(D_METHOD("set_custom", "index", "custom"), &SurfaceTool::set_custom); + ClassDB::bind_method(D_METHOD("set_custom", "channel_index", "custom_color"), &SurfaceTool::set_custom); ClassDB::bind_method(D_METHOD("set_smooth_group", "index"), &SurfaceTool::set_smooth_group); ClassDB::bind_method(D_METHOD("add_triangle_fan", "vertices", "uvs", "colors", "uv2s", "normals", "tangents"), &SurfaceTool::add_triangle_fan, DEFVAL(Vector()), DEFVAL(Vector()), DEFVAL(Vector()), DEFVAL(Vector()), DEFVAL(Vector())); @@ -1315,11 +1320,11 @@ void SurfaceTool::_bind_methods() { ClassDB::bind_method(D_METHOD("optimize_indices_for_cache"), &SurfaceTool::optimize_indices_for_cache); - ClassDB::bind_method(D_METHOD("get_max_axis_length"), &SurfaceTool::get_max_axis_length); + ClassDB::bind_method(D_METHOD("get_aabb"), &SurfaceTool::get_aabb); ClassDB::bind_method(D_METHOD("generate_lod", "nd_threshold", "target_index_count"), &SurfaceTool::generate_lod, DEFVAL(3)); ClassDB::bind_method(D_METHOD("set_material", "material"), &SurfaceTool::set_material); - ClassDB::bind_method(D_METHOD("get_primitive"), &SurfaceTool::get_primitive); + ClassDB::bind_method(D_METHOD("get_primitive_type"), &SurfaceTool::get_primitive_type); ClassDB::bind_method(D_METHOD("clear"), &SurfaceTool::clear); diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index bf4332ad2ac..2d399ca3bf4 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -154,10 +154,10 @@ public: void set_skin_weight_count(SkinWeightCount p_weights); SkinWeightCount get_skin_weight_count() const; - void set_custom_format(int p_index, CustomFormat p_format); - CustomFormat get_custom_format(int p_index) const; + void set_custom_format(int p_channel_index, CustomFormat p_format); + CustomFormat get_custom_format(int p_channel_index) const; - Mesh::PrimitiveType get_primitive() const; + Mesh::PrimitiveType get_primitive_type() const; void begin(Mesh::PrimitiveType p_primitive); @@ -166,7 +166,7 @@ public: void set_tangent(const Plane &p_tangent); void set_uv(const Vector2 &p_uv); void set_uv2(const Vector2 &p_uv2); - void set_custom(int p_index, const Color &p_custom); + void set_custom(int p_channel_index, const Color &p_custom); void set_bones(const Vector &p_bones); void set_weights(const Vector &p_weights); void set_smooth_group(uint32_t p_group); @@ -183,7 +183,7 @@ public: void generate_tangents(); void optimize_indices_for_cache(); - float get_max_axis_length() const; + AABB get_aabb() const; Vector generate_lod(float p_threshold, int p_target_index_count = 3); void set_material(const Ref &p_material); @@ -199,7 +199,7 @@ public: void create_from(const Ref &p_existing, int p_surface); void create_from_blend_shape(const Ref &p_existing, int p_surface, const String &p_blend_shape_name); void append_from(const Ref &p_existing, int p_surface, const Transform3D &p_xform); - Ref commit(const Ref &p_existing = Ref(), uint32_t p_flags = 0); + Ref commit(const Ref &p_existing = Ref(), uint32_t p_compress_flags = 0); SurfaceTool(); };