summaryrefslogtreecommitdiff
path: root/scene/resources
diff options
context:
space:
mode:
authorreduz <reduzio@gmail.com>2020-12-01 22:40:47 -0300
committerreduz <reduzio@gmail.com>2020-12-02 13:07:59 -0300
commit70f5972905a5ea6916e9aab909f9a34b963f67b1 (patch)
treef9bca7f6950e8a69fd61c0ea8b341a4976accb80 /scene/resources
parent3beab2646fa8744a84382d9fcfb73848404fe5b5 (diff)
Refactored Mesh internals and formats.
-Changed how mesh data is organized, hoping to make it more efficient on Vulkan and GLES. -Removed compression, it now always uses the most efficient format. -Added support for custom arrays (up to 8 custom formats) -Added support for 8 weights in skeleton data. -Added a simple optional versioning system for imported assets, to reimport if binary is newer -Fixes #43979 (I needed to test) WARNING: -NOT backwards compatible with previous 4.x-devel, will most likely never be, but it will force reimport scenes due to version change. -NOT backwards compatible with 3.x scenes, this will be eventually re-added. -Skeletons not working any longer, will fix in next PR.
Diffstat (limited to 'scene/resources')
-rw-r--r--scene/resources/mesh.cpp202
-rw-r--r--scene/resources/mesh.h72
-rw-r--r--scene/resources/primitive_meshes.cpp2
-rw-r--r--scene/resources/surface_tool.cpp433
-rw-r--r--scene/resources/surface_tool.h61
5 files changed, 559 insertions, 211 deletions
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 97c0c7a81d..64579e1e37 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -157,7 +157,7 @@ void Mesh::generate_debug_mesh_indices(Vector<Vector3> &r_points) {
bool Mesh::surface_is_softbody_friendly(int p_idx) const {
const uint32_t surface_format = surface_get_format(p_idx);
- return (surface_format & Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE && (!(surface_format & Mesh::ARRAY_COMPRESS_NORMAL)));
+ return (surface_format & Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE);
}
Vector<Face3> Mesh::get_faces() const {
@@ -483,37 +483,59 @@ void Mesh::_bind_methods() {
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED);
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE);
+ BIND_ENUM_CONSTANT(ARRAY_VERTEX);
+ BIND_ENUM_CONSTANT(ARRAY_NORMAL);
+ BIND_ENUM_CONSTANT(ARRAY_TANGENT);
+ BIND_ENUM_CONSTANT(ARRAY_COLOR);
+ BIND_ENUM_CONSTANT(ARRAY_TEX_UV);
+ BIND_ENUM_CONSTANT(ARRAY_TEX_UV2);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM0);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM1);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM2);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM3);
+ BIND_ENUM_CONSTANT(ARRAY_BONES);
+ BIND_ENUM_CONSTANT(ARRAY_WEIGHTS);
+ BIND_ENUM_CONSTANT(ARRAY_INDEX);
+ BIND_ENUM_CONSTANT(ARRAY_MAX);
+
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_UNORM);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_SNORM);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_HALF);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_HALF);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_R_FLOAT);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_FLOAT);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGB_FLOAT);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_FLOAT);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_MAX);
+
BIND_ENUM_CONSTANT(ARRAY_FORMAT_VERTEX);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_NORMAL);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TANGENT);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_COLOR);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV2);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM3);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_NORMAL);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TANGENT);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_COLOR);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV2);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_INDEX);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_BLEND_SHAPE_MASK);
- BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_BASE);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0_SHIFT);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1_SHIFT);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2_SHIFT);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM3_SHIFT);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_DEFAULT);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_MASK);
+ BIND_ENUM_CONSTANT(ARRAY_COMPRESS_FLAGS_BASE);
- BIND_ENUM_CONSTANT(ARRAY_VERTEX);
- BIND_ENUM_CONSTANT(ARRAY_NORMAL);
- BIND_ENUM_CONSTANT(ARRAY_TANGENT);
- BIND_ENUM_CONSTANT(ARRAY_COLOR);
- BIND_ENUM_CONSTANT(ARRAY_TEX_UV);
- BIND_ENUM_CONSTANT(ARRAY_TEX_UV2);
- BIND_ENUM_CONSTANT(ARRAY_BONES);
- BIND_ENUM_CONSTANT(ARRAY_WEIGHTS);
- BIND_ENUM_CONSTANT(ARRAY_INDEX);
- BIND_ENUM_CONSTANT(ARRAY_MAX);
+ BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES);
+ BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_DYNAMIC_UPDATE);
+ BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_8_BONE_WEIGHTS);
}
void Mesh::clear_cache() const {
@@ -559,12 +581,50 @@ Vector<Ref<Shape3D>> Mesh::convex_decompose() const {
Mesh::Mesh() {
}
-
+#if 0
static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_format, uint32_t p_elements) {
- bool vertex_16bit = p_format & ((1 << (Mesh::ARRAY_VERTEX + Mesh::ARRAY_COMPRESS_BASE)));
- bool has_bones = (p_format & Mesh::ARRAY_FORMAT_BONES);
- bool bone_8 = has_bones && !(p_format & (Mesh::ARRAY_COMPRESS_INDEX << 2));
- bool weight_32 = has_bones && !(p_format & (Mesh::ARRAY_COMPRESS_TEX_UV2 << 2));
+ enum ArrayType {
+ OLD_ARRAY_VERTEX = 0,
+ OLD_ARRAY_NORMAL = 1,
+ OLD_ARRAY_TANGENT = 2,
+ OLD_ARRAY_COLOR = 3,
+ OLD_ARRAY_TEX_UV = 4,
+ OLD_ARRAY_TEX_UV2 = 5,
+ OLD_ARRAY_BONES = 6,
+ OLD_ARRAY_WEIGHTS = 7,
+ OLD_ARRAY_INDEX = 8,
+ OLD_ARRAY_MAX = 9
+ };
+
+ enum ArrayFormat {
+ /* OLD_ARRAY FORMAT FLAGS */
+ OLD_ARRAY_FORMAT_VERTEX = 1 << OLD_ARRAY_VERTEX, // mandatory
+ OLD_ARRAY_FORMAT_NORMAL = 1 << OLD_ARRAY_NORMAL,
+ OLD_ARRAY_FORMAT_TANGENT = 1 << OLD_ARRAY_TANGENT,
+ OLD_ARRAY_FORMAT_COLOR = 1 << OLD_ARRAY_COLOR,
+ OLD_ARRAY_FORMAT_TEX_UV = 1 << OLD_ARRAY_TEX_UV,
+ OLD_ARRAY_FORMAT_TEX_UV2 = 1 << OLD_ARRAY_TEX_UV2,
+ OLD_ARRAY_FORMAT_BONES = 1 << OLD_ARRAY_BONES,
+ OLD_ARRAY_FORMAT_WEIGHTS = 1 << OLD_ARRAY_WEIGHTS,
+ OLD_ARRAY_FORMAT_INDEX = 1 << OLD_ARRAY_INDEX,
+
+ OLD_ARRAY_COMPRESS_BASE = (OLD_ARRAY_INDEX + 1),
+ OLD_ARRAY_COMPRESS_NORMAL = 1 << (OLD_ARRAY_NORMAL + OLD_ARRAY_COMPRESS_BASE),
+ OLD_ARRAY_COMPRESS_TANGENT = 1 << (OLD_ARRAY_TANGENT + OLD_ARRAY_COMPRESS_BASE),
+ OLD_ARRAY_COMPRESS_COLOR = 1 << (OLD_ARRAY_COLOR + OLD_ARRAY_COMPRESS_BASE),
+ OLD_ARRAY_COMPRESS_TEX_UV = 1 << (OLD_ARRAY_TEX_UV + OLD_ARRAY_COMPRESS_BASE),
+ OLD_ARRAY_COMPRESS_TEX_UV2 = 1 << (OLD_ARRAY_TEX_UV2 + OLD_ARRAY_COMPRESS_BASE),
+ OLD_ARRAY_COMPRESS_INDEX = 1 << (OLD_ARRAY_INDEX + OLD_ARRAY_COMPRESS_BASE),
+ OLD_ARRAY_COMPRESS_DEFAULT = OLD_ARRAY_COMPRESS_NORMAL | OLD_ARRAY_COMPRESS_TANGENT | OLD_ARRAY_COMPRESS_COLOR | OLD_ARRAY_COMPRESS_TEX_UV | OLD_ARRAY_COMPRESS_TEX_UV2,
+
+ OLD_ARRAY_FLAG_USE_2D_VERTICES = OLD_ARRAY_COMPRESS_INDEX << 1,
+ OLD_ARRAY_FLAG_USE_DYNAMIC_UPDATE = OLD_ARRAY_COMPRESS_INDEX << 3,
+ };
+
+ bool vertex_16bit = p_format & ((1 << (OLD_ARRAY_VERTEX + OLD_ARRAY_COMPRESS_BASE)));
+ bool has_bones = (p_format & OLD_ARRAY_FORMAT_BONES);
+ bool bone_8 = has_bones && !(p_format & (OLD_ARRAY_COMPRESS_INDEX << 2));
+ bool weight_32 = has_bones && !(p_format & (OLD_ARRAY_COMPRESS_TEX_UV2 << 2));
print_line("convert vertex16: " + itos(vertex_16bit) + " convert bone 8 " + itos(bone_8) + " convert weight 32 " + itos(weight_32));
@@ -572,7 +632,7 @@ static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, ui
return p_src;
}
- bool vertex_2d = (p_format & (Mesh::ARRAY_COMPRESS_INDEX << 1));
+ bool vertex_2d = (p_format & (OLD_ARRAY_COMPRESS_INDEX << 1));
uint32_t src_stride = p_src.size() / p_elements;
uint32_t dst_stride = src_stride + (vertex_16bit ? 4 : 0) + (bone_8 ? 4 : 0) - (weight_32 ? 8 : 0);
@@ -671,7 +731,7 @@ static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, ui
return ret;
}
-
+#endif
bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
String sname = p_name;
@@ -727,6 +787,7 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
add_surface_from_arrays(PrimitiveType(int(d["primitive"])), d["arrays"], d["morph_arrays"]);
} else if (d.has("array_data")) {
+#if 0
//print_line("array data (old style");
//older format (3.x)
Vector<uint8_t> array_data = d["array_data"];
@@ -793,6 +854,7 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
}
add_surface(format, PrimitiveType(primitive), array_data, vertex_count, array_index_data, index_count, aabb, blend_shapes, bone_aabb);
+#endif
} else {
ERR_FAIL_V(false);
}
@@ -824,6 +886,12 @@ Array ArrayMesh::_get_surfaces() const {
data["primitive"] = surface.primitive;
data["vertex_data"] = surface.vertex_data;
data["vertex_count"] = surface.vertex_count;
+ if (surface.skin_data.size()) {
+ data["skin_data"] = surface.skin_data;
+ }
+ if (surface.attribute_data.size()) {
+ data["attribute_data"] = surface.attribute_data;
+ }
data["aabb"] = surface.aabb;
if (surface.index_count) {
data["index_data"] = surface.index_data;
@@ -848,9 +916,9 @@ Array ArrayMesh::_get_surfaces() const {
data["bone_aabbs"] = bone_aabbs;
}
- Array blend_shapes;
- for (int j = 0; j < surface.blend_shapes.size(); j++) {
- blend_shapes.push_back(surface.blend_shapes[j]);
+ if (surface.blend_shape_data.size()) {
+ data["blend_shapes"] = surface.blend_shape_data;
+ data["blend_shapes_count"] = surface.blend_shape_count;
}
if (surfaces[i].material.is_valid()) {
@@ -896,6 +964,12 @@ void ArrayMesh::_set_surfaces(const Array &p_surfaces) {
surface.primitive = RS::PrimitiveType(int(d["primitive"]));
surface.vertex_data = d["vertex_data"];
surface.vertex_count = d["vertex_count"];
+ if (d.has("attribute_data")) {
+ surface.attribute_data = d["attribute_data"];
+ }
+ if (d.has("skin_data")) {
+ surface.skin_data = d["skin_data"];
+ }
surface.aabb = d["aabb"];
if (d.has("index_data")) {
@@ -922,11 +996,9 @@ void ArrayMesh::_set_surfaces(const Array &p_surfaces) {
}
}
- if (d.has("blend_shapes")) {
- Array blend_shapes;
- for (int j = 0; j < blend_shapes.size(); j++) {
- surface.blend_shapes.push_back(blend_shapes[j]);
- }
+ if (d.has("blend_shapes") && d.has("blend_shape_count")) {
+ surface.blend_shape_data = d["blend_shapes"];
+ surface.blend_shape_count = d["blend_shape_count"];
}
Ref<Material> material;
@@ -982,7 +1054,7 @@ void ArrayMesh::_set_surfaces(const Array &p_surfaces) {
s.aabb = surface_data[i].aabb;
if (i == 0) {
aabb = s.aabb;
- blend_shapes.resize(surface_data[i].blend_shapes.size());
+ blend_shapes.resize(surface_data[i].blend_shape_count);
} else {
aabb.merge_with(s.aabb);
}
@@ -1070,7 +1142,7 @@ void ArrayMesh::_recompute_aabb() {
#ifndef _MSC_VER
#warning need to add binding to add_surface using future MeshSurfaceData object
#endif
-void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<Vector<uint8_t>> &p_blend_shapes, const Vector<AABB> &p_bone_aabb, const Vector<RS::SurfaceData::LOD> &p_lods) {
+void ArrayMesh::add_surface(uint32_t 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, uint32_t p_blend_shape_count, const Vector<AABB> &p_bone_aabbs, const Vector<RS::SurfaceData::LOD> &p_lods) {
_create_if_empty();
Surface s;
@@ -1090,10 +1162,13 @@ void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const
sd.aabb = p_aabb;
sd.vertex_count = p_vertex_count;
sd.vertex_data = p_array;
+ sd.attribute_data = p_attribute_array;
+ sd.skin_data = p_skin_array;
sd.index_count = p_index_count;
sd.index_data = p_index_array;
- sd.blend_shapes = p_blend_shapes;
- sd.bone_aabbs = p_bone_aabb;
+ sd.blend_shape_data = p_blend_shape_data;
+ sd.blend_shape_count = p_blend_shape_count;
+ sd.bone_aabbs = p_bone_aabbs;
sd.lods = p_lods;
RenderingServer::get_singleton()->mesh_add_surface(mesh, sd);
@@ -1119,7 +1194,7 @@ void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &
print_line("index count: " + itos(surface.index_count));
print_line("primitive: " + itos(surface.primitive));
*/
- add_surface(surface.format, PrimitiveType(surface.primitive), surface.vertex_data, surface.vertex_count, surface.index_data, surface.index_count, surface.aabb, surface.blend_shapes, surface.bone_aabbs, surface.lods);
+ 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.blend_shape_count, surface.bone_aabbs, surface.lods);
}
Array ArrayMesh::surface_get_arrays(int p_surface) const {
@@ -1452,29 +1527,29 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach
SurfaceTool::Vertex v = lightmap_surfaces[surface].vertices[uv_indices[gen_vertices[gen_indices[i + j]]].second];
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_COLOR) {
- surfaces_tools.write[surface]->add_color(v.color);
+ surfaces_tools.write[surface]->set_color(v.color);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TEX_UV) {
- surfaces_tools.write[surface]->add_uv(v.uv);
+ surfaces_tools.write[surface]->set_uv(v.uv);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_NORMAL) {
- surfaces_tools.write[surface]->add_normal(v.normal);
+ surfaces_tools.write[surface]->set_normal(v.normal);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TANGENT) {
Plane t;
t.normal = v.tangent;
t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1;
- surfaces_tools.write[surface]->add_tangent(t);
+ surfaces_tools.write[surface]->set_tangent(t);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_BONES) {
- surfaces_tools.write[surface]->add_bones(v.bones);
+ surfaces_tools.write[surface]->set_bones(v.bones);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) {
- surfaces_tools.write[surface]->add_weights(v.weights);
+ surfaces_tools.write[surface]->set_weights(v.weights);
}
Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]);
- surfaces_tools.write[surface]->add_uv2(uv2);
+ surfaces_tools.write[surface]->set_uv2(uv2);
surfaces_tools.write[surface]->add_vertex(v.vertex);
}
@@ -1507,7 +1582,7 @@ void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &ArrayMesh::set_blend_shape_mode);
ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &ArrayMesh::get_blend_shape_mode);
- ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "lods", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(ARRAY_COMPRESS_DEFAULT));
+ ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "lods", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(0));
ClassDB::bind_method(D_METHOD("clear_surfaces"), &ArrayMesh::clear_surfaces);
ClassDB::bind_method(D_METHOD("surface_update_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_region);
ClassDB::bind_method(D_METHOD("surface_get_array_len", "surf_idx"), &ArrayMesh::surface_get_array_len);
@@ -1546,20 +1621,53 @@ void ArrayMesh::_bind_methods() {
BIND_ENUM_CONSTANT(ARRAY_COLOR);
BIND_ENUM_CONSTANT(ARRAY_TEX_UV);
BIND_ENUM_CONSTANT(ARRAY_TEX_UV2);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM0);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM1);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM2);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM3);
BIND_ENUM_CONSTANT(ARRAY_BONES);
BIND_ENUM_CONSTANT(ARRAY_WEIGHTS);
BIND_ENUM_CONSTANT(ARRAY_INDEX);
BIND_ENUM_CONSTANT(ARRAY_MAX);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_UNORM);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_SNORM);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_HALF);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_HALF);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_R_FLOAT);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_FLOAT);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGB_FLOAT);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_FLOAT);
+ BIND_ENUM_CONSTANT(ARRAY_CUSTOM_MAX);
+
BIND_ENUM_CONSTANT(ARRAY_FORMAT_VERTEX);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_NORMAL);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TANGENT);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_COLOR);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV2);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM3);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX);
+
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_BLEND_SHAPE_MASK);
+
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_BASE);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0_SHIFT);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1_SHIFT);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2_SHIFT);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM3_SHIFT);
+
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_MASK);
+ BIND_ENUM_CONSTANT(ARRAY_COMPRESS_FLAGS_BASE);
+
+ BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES);
+ BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_DYNAMIC_UPDATE);
+ BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_8_BONE_WEIGHTS);
}
void ArrayMesh::reload_from_file() {
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 642ae7e1b0..659574c2c4 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -61,6 +61,10 @@ public:
ARRAY_COLOR = RenderingServer::ARRAY_COLOR,
ARRAY_TEX_UV = RenderingServer::ARRAY_TEX_UV,
ARRAY_TEX_UV2 = RenderingServer::ARRAY_TEX_UV2,
+ ARRAY_CUSTOM0 = RenderingServer::ARRAY_CUSTOM0,
+ ARRAY_CUSTOM1 = RenderingServer::ARRAY_CUSTOM1,
+ ARRAY_CUSTOM2 = RenderingServer::ARRAY_CUSTOM2,
+ ARRAY_CUSTOM3 = RenderingServer::ARRAY_CUSTOM3,
ARRAY_BONES = RenderingServer::ARRAY_BONES,
ARRAY_WEIGHTS = RenderingServer::ARRAY_WEIGHTS,
ARRAY_INDEX = RenderingServer::ARRAY_INDEX,
@@ -68,30 +72,47 @@ public:
};
+ enum ArrayCustomFormat {
+ ARRAY_CUSTOM_RGBA8_UNORM,
+ ARRAY_CUSTOM_RGBA8_SNORM,
+ ARRAY_CUSTOM_RG_HALF,
+ ARRAY_CUSTOM_RGBA_HALF,
+ ARRAY_CUSTOM_R_FLOAT,
+ ARRAY_CUSTOM_RG_FLOAT,
+ ARRAY_CUSTOM_RGB_FLOAT,
+ ARRAY_CUSTOM_RGBA_FLOAT,
+ ARRAY_CUSTOM_MAX
+ };
+
enum ArrayFormat {
- /* ARRAY FORMAT FLAGS */
- ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // mandatory
- ARRAY_FORMAT_NORMAL = 1 << ARRAY_NORMAL,
- ARRAY_FORMAT_TANGENT = 1 << ARRAY_TANGENT,
- ARRAY_FORMAT_COLOR = 1 << ARRAY_COLOR,
- ARRAY_FORMAT_TEX_UV = 1 << ARRAY_TEX_UV,
- ARRAY_FORMAT_TEX_UV2 = 1 << ARRAY_TEX_UV2,
- ARRAY_FORMAT_BONES = 1 << ARRAY_BONES,
- ARRAY_FORMAT_WEIGHTS = 1 << ARRAY_WEIGHTS,
- ARRAY_FORMAT_INDEX = 1 << ARRAY_INDEX,
-
- ARRAY_COMPRESS_BASE = (ARRAY_INDEX + 1),
- ARRAY_COMPRESS_NORMAL = 1 << (ARRAY_NORMAL + ARRAY_COMPRESS_BASE),
- ARRAY_COMPRESS_TANGENT = 1 << (ARRAY_TANGENT + ARRAY_COMPRESS_BASE),
- ARRAY_COMPRESS_COLOR = 1 << (ARRAY_COLOR + ARRAY_COMPRESS_BASE),
- ARRAY_COMPRESS_TEX_UV = 1 << (ARRAY_TEX_UV + ARRAY_COMPRESS_BASE),
- ARRAY_COMPRESS_TEX_UV2 = 1 << (ARRAY_TEX_UV2 + ARRAY_COMPRESS_BASE),
- ARRAY_COMPRESS_INDEX = 1 << (ARRAY_INDEX + ARRAY_COMPRESS_BASE),
-
- ARRAY_FLAG_USE_2D_VERTICES = ARRAY_COMPRESS_INDEX << 1,
- ARRAY_FLAG_USE_DYNAMIC_UPDATE = ARRAY_COMPRESS_INDEX << 3,
-
- ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2
+ ARRAY_FORMAT_VERTEX = RS::ARRAY_FORMAT_VERTEX,
+ ARRAY_FORMAT_NORMAL = RS::ARRAY_FORMAT_NORMAL,
+ ARRAY_FORMAT_TANGENT = RS::ARRAY_FORMAT_TANGENT,
+ ARRAY_FORMAT_COLOR = RS::ARRAY_FORMAT_COLOR,
+ ARRAY_FORMAT_TEX_UV = RS::ARRAY_FORMAT_TEX_UV,
+ ARRAY_FORMAT_TEX_UV2 = RS::ARRAY_FORMAT_TEX_UV2,
+ ARRAY_FORMAT_CUSTOM0 = RS::ARRAY_FORMAT_CUSTOM0,
+ ARRAY_FORMAT_CUSTOM1 = RS::ARRAY_FORMAT_CUSTOM1,
+ ARRAY_FORMAT_CUSTOM2 = RS::ARRAY_FORMAT_CUSTOM2,
+ ARRAY_FORMAT_CUSTOM3 = RS::ARRAY_FORMAT_CUSTOM3,
+ ARRAY_FORMAT_BONES = RS::ARRAY_FORMAT_BONES,
+ ARRAY_FORMAT_WEIGHTS = RS::ARRAY_FORMAT_WEIGHTS,
+ ARRAY_FORMAT_INDEX = RS::ARRAY_FORMAT_INDEX,
+
+ ARRAY_FORMAT_BLEND_SHAPE_MASK = RS::ARRAY_FORMAT_BLEND_SHAPE_MASK,
+
+ ARRAY_FORMAT_CUSTOM_BASE = RS::ARRAY_FORMAT_CUSTOM_BASE,
+ ARRAY_FORMAT_CUSTOM0_SHIFT = RS::ARRAY_FORMAT_CUSTOM0_SHIFT,
+ ARRAY_FORMAT_CUSTOM1_SHIFT = RS::ARRAY_FORMAT_CUSTOM1_SHIFT,
+ ARRAY_FORMAT_CUSTOM2_SHIFT = RS::ARRAY_FORMAT_CUSTOM2_SHIFT,
+ ARRAY_FORMAT_CUSTOM3_SHIFT = RS::ARRAY_FORMAT_CUSTOM3_SHIFT,
+
+ ARRAY_FORMAT_CUSTOM_MASK = RS::ARRAY_FORMAT_CUSTOM_MASK,
+ ARRAY_COMPRESS_FLAGS_BASE = RS::ARRAY_COMPRESS_FLAGS_BASE,
+
+ ARRAY_FLAG_USE_2D_VERTICES = RS::ARRAY_FLAG_USE_2D_VERTICES,
+ ARRAY_FLAG_USE_DYNAMIC_UPDATE = RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE,
+ ARRAY_FLAG_USE_8_BONE_WEIGHTS = RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS,
};
@@ -187,9 +208,9 @@ protected:
static void _bind_methods();
public:
- void add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_flags = ARRAY_COMPRESS_DEFAULT);
+ void add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_flags = 0);
- void add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<Vector<uint8_t>> &p_blend_shapes = Vector<Vector<uint8_t>>(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>(), const Vector<RS::SurfaceData::LOD> &p_lods = Vector<RS::SurfaceData::LOD>());
+ void add_surface(uint32_t 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 = Vector<uint8_t>(), uint32_t p_blend_shape_count = 0, const Vector<AABB> &p_bone_aabbs = Vector<AABB>(), const Vector<RS::SurfaceData::LOD> &p_lods = Vector<RS::SurfaceData::LOD>());
Array surface_get_arrays(int p_surface) const override;
Array surface_get_blend_shape_arrays(int p_surface) const override;
@@ -244,6 +265,7 @@ public:
VARIANT_ENUM_CAST(Mesh::ArrayType);
VARIANT_ENUM_CAST(Mesh::ArrayFormat);
+VARIANT_ENUM_CAST(Mesh::ArrayCustomFormat);
VARIANT_ENUM_CAST(Mesh::PrimitiveType);
VARIANT_ENUM_CAST(Mesh::BlendShapeMode);
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 8d9c5f07b2..64322f333c 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -148,7 +148,7 @@ Array PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) const {
uint32_t PrimitiveMesh::surface_get_format(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, 1, 0);
- return RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX | RS::ARRAY_COMPRESS_DEFAULT;
+ return RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX;
}
Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const {
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index ff14a5a292..3166067573 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -74,6 +74,12 @@ bool SurfaceTool::Vertex::operator==(const Vertex &p_vertex) const {
}
}
+ for (int i = 0; i < RS::ARRAY_CUSTOM_MAX; i++) {
+ if (custom[i] != p_vertex.custom[i]) {
+ return false;
+ }
+ }
+
return true;
}
@@ -87,6 +93,7 @@ uint32_t SurfaceTool::VertexHasher::hash(const Vertex &p_vtx) {
h = hash_djb2_buffer((const uint8_t *)&p_vtx.color, sizeof(real_t) * 4, h);
h = hash_djb2_buffer((const uint8_t *)p_vtx.bones.ptr(), p_vtx.bones.size() * sizeof(int), h);
h = hash_djb2_buffer((const uint8_t *)p_vtx.weights.ptr(), p_vtx.weights.size() * sizeof(float), h);
+ h = hash_djb2_buffer((const uint8_t *)&p_vtx.custom[0], sizeof(Color) * RS::ARRAY_CUSTOM_COUNT, h);
return h;
}
@@ -111,8 +118,11 @@ void SurfaceTool::add_vertex(const Vector3 &p_vertex) {
vtx.bones = last_bones;
vtx.tangent = last_tangent.normal;
vtx.binormal = last_normal.cross(last_tangent.normal).normalized() * last_tangent.d;
+ for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
+ vtx.custom[i] = last_custom[i];
+ }
- const int expected_vertices = 4;
+ const int expected_vertices = skin_weights == SKIN_8_WEIGHTS ? 8 : 4;
if ((format & Mesh::ARRAY_FORMAT_WEIGHTS || format & Mesh::ARRAY_FORMAT_BONES) && (vtx.weights.size() != expected_vertices || vtx.bones.size() != expected_vertices)) {
//ensure vertices are the expected amount
@@ -163,7 +173,7 @@ void SurfaceTool::add_vertex(const Vector3 &p_vertex) {
format |= Mesh::ARRAY_FORMAT_VERTEX;
}
-void SurfaceTool::add_color(Color p_color) {
+void SurfaceTool::set_color(Color p_color) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_COLOR));
@@ -172,7 +182,7 @@ void SurfaceTool::add_color(Color p_color) {
last_color = p_color;
}
-void SurfaceTool::add_normal(const Vector3 &p_normal) {
+void SurfaceTool::set_normal(const Vector3 &p_normal) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_NORMAL));
@@ -181,7 +191,7 @@ void SurfaceTool::add_normal(const Vector3 &p_normal) {
last_normal = p_normal;
}
-void SurfaceTool::add_tangent(const Plane &p_tangent) {
+void SurfaceTool::set_tangent(const Plane &p_tangent) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_TANGENT));
@@ -189,7 +199,7 @@ void SurfaceTool::add_tangent(const Plane &p_tangent) {
last_tangent = p_tangent;
}
-void SurfaceTool::add_uv(const Vector2 &p_uv) {
+void SurfaceTool::set_uv(const Vector2 &p_uv) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_TEX_UV));
@@ -197,7 +207,7 @@ void SurfaceTool::add_uv(const Vector2 &p_uv) {
last_uv = p_uv;
}
-void SurfaceTool::add_uv2(const Vector2 &p_uv2) {
+void SurfaceTool::set_uv2(const Vector2 &p_uv2) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_TEX_UV2));
@@ -205,19 +215,40 @@ void SurfaceTool::add_uv2(const Vector2 &p_uv2) {
last_uv2 = p_uv2;
}
-void SurfaceTool::add_bones(const Vector<int> &p_bones) {
+void SurfaceTool::set_custom(int p_index, const Color &p_custom) {
+ ERR_FAIL_INDEX(p_index, RS::ARRAY_CUSTOM_COUNT);
+ ERR_FAIL_COND(!begun);
+ ERR_FAIL_COND(last_custom_format[p_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]));
+
+ if (first) {
+ format |= mask[p_index];
+ format |= last_custom_format[p_index] << shift[p_index];
+ }
+ last_custom[p_index] = p_custom;
+}
+
+void SurfaceTool::set_bones(const Vector<int> &p_bones) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_BONES));
format |= Mesh::ARRAY_FORMAT_BONES;
+ if (skin_weights == SKIN_8_WEIGHTS) {
+ format |= Mesh::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
+ }
last_bones = p_bones;
}
-void SurfaceTool::add_weights(const Vector<float> &p_weights) {
+void SurfaceTool::set_weights(const Vector<float> &p_weights) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_WEIGHTS));
format |= Mesh::ARRAY_FORMAT_WEIGHTS;
+ if (skin_weights == SKIN_8_WEIGHTS) {
+ format |= Mesh::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
+ }
last_weights = p_weights;
}
@@ -238,15 +269,15 @@ void SurfaceTool::add_triangle_fan(const Vector<Vector3> &p_vertices, const Vect
#define ADD_POINT(n) \
{ \
if (p_colors.size() > n) \
- add_color(p_colors[n]); \
+ set_color(p_colors[n]); \
if (p_uvs.size() > n) \
- add_uv(p_uvs[n]); \
+ set_uv(p_uvs[n]); \
if (p_uv2s.size() > n) \
- add_uv2(p_uv2s[n]); \
+ set_uv2(p_uv2s[n]); \
if (p_normals.size() > n) \
- add_normal(p_normals[n]); \
+ set_normal(p_normals[n]); \
if (p_tangents.size() > n) \
- add_tangent(p_tangents[n]); \
+ set_tangent(p_tangents[n]); \
add_vertex(p_vertices[n]); \
}
@@ -358,18 +389,157 @@ Array SurfaceTool::commit_to_arrays() {
a[i] = array;
} break;
+ case Mesh::ARRAY_CUSTOM0:
+ case Mesh::ARRAY_CUSTOM1:
+ case Mesh::ARRAY_CUSTOM2:
+ case Mesh::ARRAY_CUSTOM3: {
+ int fmt = i - Mesh::ARRAY_CUSTOM0;
+ switch (last_custom_format[fmt]) {
+ case CUSTOM_RGBA8_UNORM: {
+ Vector<uint8_t> array;
+ array.resize(varr_len * 4);
+ uint8_t *w = array.ptrw();
+
+ int idx = 0;
+ for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
+ const Vertex &v = E->get();
+ const Color &c = v.custom[idx];
+ w[idx * 4 + 0] = CLAMP(int32_t(c.r * 255.0), 0, 255);
+ w[idx * 4 + 1] = CLAMP(int32_t(c.g * 255.0), 0, 255);
+ w[idx * 4 + 2] = CLAMP(int32_t(c.b * 255.0), 0, 255);
+ w[idx * 4 + 3] = CLAMP(int32_t(c.a * 255.0), 0, 255);
+ }
+
+ a[i] = array;
+ } break;
+ case CUSTOM_RGBA8_SNORM: {
+ Vector<uint8_t> array;
+ array.resize(varr_len * 4);
+ uint8_t *w = array.ptrw();
+
+ int idx = 0;
+ for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
+ const Vertex &v = E->get();
+ const Color &c = v.custom[idx];
+ w[idx * 4 + 0] = uint8_t(int8_t(CLAMP(int32_t(c.r * 127.0), -128, 127)));
+ w[idx * 4 + 1] = uint8_t(int8_t(CLAMP(int32_t(c.g * 127.0), -128, 127)));
+ w[idx * 4 + 2] = uint8_t(int8_t(CLAMP(int32_t(c.b * 127.0), -128, 127)));
+ w[idx * 4 + 3] = uint8_t(int8_t(CLAMP(int32_t(c.a * 127.0), -128, 127)));
+ }
+
+ a[i] = array;
+ } break;
+ case CUSTOM_RG_HALF: {
+ Vector<uint8_t> array;
+ array.resize(varr_len * 4);
+ uint16_t *w = (uint16_t *)array.ptrw();
+
+ int idx = 0;
+ for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
+ const Vertex &v = E->get();
+ const Color &c = v.custom[idx];
+ w[idx * 2 + 0] = Math::make_half_float(c.r);
+ w[idx * 2 + 1] = Math::make_half_float(c.g);
+ }
+
+ a[i] = array;
+ } break;
+ case CUSTOM_RGBA_HALF: {
+ Vector<uint8_t> array;
+ array.resize(varr_len * 8);
+ uint16_t *w = (uint16_t *)array.ptrw();
+
+ int idx = 0;
+ for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
+ const Vertex &v = E->get();
+ const Color &c = v.custom[idx];
+ w[idx * 4 + 0] = Math::make_half_float(c.r);
+ w[idx * 4 + 1] = Math::make_half_float(c.g);
+ w[idx * 4 + 2] = Math::make_half_float(c.b);
+ w[idx * 4 + 3] = Math::make_half_float(c.a);
+ }
+
+ a[i] = array;
+ } break;
+ case CUSTOM_R_FLOAT: {
+ Vector<float> array;
+ array.resize(varr_len);
+ float *w = (float *)array.ptrw();
+
+ int idx = 0;
+ for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
+ const Vertex &v = E->get();
+ const Color &c = v.custom[idx];
+ w[idx] = c.r;
+ }
+
+ a[i] = array;
+ } break;
+ case CUSTOM_RG_FLOAT: {
+ Vector<float> array;
+ array.resize(varr_len * 2);
+ float *w = (float *)array.ptrw();
+
+ int idx = 0;
+ for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
+ const Vertex &v = E->get();
+ const Color &c = v.custom[idx];
+ w[idx * 2 + 0] = c.r;
+ w[idx * 2 + 1] = c.g;
+ }
+
+ a[i] = array;
+ } break;
+ case CUSTOM_RGB_FLOAT: {
+ Vector<float> array;
+ array.resize(varr_len * 3);
+ float *w = (float *)array.ptrw();
+
+ int idx = 0;
+ for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
+ const Vertex &v = E->get();
+ const Color &c = v.custom[idx];
+ w[idx * 3 + 0] = c.r;
+ w[idx * 3 + 1] = c.g;
+ w[idx * 3 + 2] = c.b;
+ }
+
+ a[i] = array;
+ } break;
+ case CUSTOM_RGBA_FLOAT: {
+ Vector<float> array;
+ array.resize(varr_len * 4);
+ float *w = (float *)array.ptrw();
+
+ int idx = 0;
+ for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
+ const Vertex &v = E->get();
+ const Color &c = v.custom[idx];
+ w[idx * 4 + 0] = c.r;
+ w[idx * 4 + 1] = c.g;
+ w[idx * 4 + 2] = c.b;
+ w[idx * 4 + 3] = c.a;
+ }
+
+ a[i] = array;
+ } break;
+ default: {
+ } //unreachable but compiler warning anyway
+ }
+ } break;
case Mesh::ARRAY_BONES: {
+ int count = skin_weights == SKIN_8_WEIGHTS ? 8 : 4;
Vector<int> array;
- array.resize(varr_len * 4);
+ array.resize(varr_len * count);
int *w = array.ptrw();
int idx = 0;
- for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx += 4) {
+ for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx += count) {
const Vertex &v = E->get();
- ERR_CONTINUE(v.bones.size() != 4);
+ ERR_CONTINUE(v.bones.size() != count);
- for (int j = 0; j < 4; j++) {
+ for (int j = 0; j < count; j++) {
w[idx + j] = v.bones[j];
}
}
@@ -379,15 +549,17 @@ Array SurfaceTool::commit_to_arrays() {
} break;
case Mesh::ARRAY_WEIGHTS: {
Vector<float> array;
- array.resize(varr_len * 4);
+ int count = skin_weights == SKIN_8_WEIGHTS ? 8 : 4;
+
+ array.resize(varr_len * count);
float *w = array.ptrw();
int idx = 0;
- for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx += 4) {
+ for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx += count) {
const Vertex &v = E->get();
- ERR_CONTINUE(v.weights.size() != 4);
+ ERR_CONTINUE(v.weights.size() != count);
- for (int j = 0; j < 4; j++) {
+ for (int j = 0; j < count; j++) {
w[idx + j] = v.weights[j];
}
}
@@ -492,13 +664,13 @@ void SurfaceTool::deindex() {
index_array.clear();
}
-void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index, int &lformat) {
+void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index, uint32_t &lformat) {
Array arr = p_existing->surface_get_arrays(p_surface);
ERR_FAIL_COND(arr.size() != RS::ARRAY_MAX);
_create_list_from_arrays(arr, r_vertex, r_index, lformat);
}
-Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays) {
+Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays, uint32_t *r_format) {
Vector<SurfaceTool::Vertex> ret;
Vector<Vector3> varr = p_arrays[RS::ARRAY_VERTEX];
@@ -509,9 +681,13 @@ Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_array
Vector<Vector2> uv2arr = p_arrays[RS::ARRAY_TEX_UV2];
Vector<int> barr = p_arrays[RS::ARRAY_BONES];
Vector<float> warr = p_arrays[RS::ARRAY_WEIGHTS];
+ Vector<float> custom_float[RS::ARRAY_CUSTOM_COUNT];
int vc = varr.size();
if (vc == 0) {
+ if (r_format) {
+ *r_format = 0;
+ }
return ret;
}
@@ -534,12 +710,40 @@ Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_array
if (uv2arr.size()) {
lformat |= RS::ARRAY_FORMAT_TEX_UV2;
}
- if (barr.size()) {
+ int wcount = 0;
+ if (barr.size() && warr.size()) {
lformat |= RS::ARRAY_FORMAT_BONES;
+ lformat |= RS::ARRAY_FORMAT_WEIGHTS;
+
+ wcount = barr.size() / varr.size();
+ if (wcount == 8) {
+ lformat |= RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
+ }
}
+
if (warr.size()) {
lformat |= RS::ARRAY_FORMAT_WEIGHTS;
}
+ static const uint32_t custom_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 custom_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++) {
+ ERR_CONTINUE_MSG(p_arrays[RS::ARRAY_CUSTOM0 + i].get_type() == Variant::PACKED_BYTE_ARRAY, "Extracting Byte/Half formats is not supported");
+ if (p_arrays[RS::ARRAY_CUSTOM0 + i].get_type() == Variant::PACKED_FLOAT32_ARRAY) {
+ lformat |= custom_mask[i];
+ custom_float[i] = p_arrays[RS::ARRAY_CUSTOM0 + i];
+ int fmt = custom_float[i].size() / varr.size();
+ if (fmt == 1) {
+ lformat |= CUSTOM_R_FLOAT << custom_shift[i];
+ } else if (fmt == 2) {
+ lformat |= CUSTOM_RG_FLOAT << custom_shift[i];
+ } else if (fmt == 3) {
+ lformat |= CUSTOM_RGB_FLOAT << custom_shift[i];
+ } else if (fmt == 4) {
+ lformat |= CUSTOM_RGBA_FLOAT << custom_shift[i];
+ }
+ }
+ }
for (int i = 0; i < vc; i++) {
Vertex v;
@@ -565,112 +769,46 @@ Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_array
}
if (lformat & RS::ARRAY_FORMAT_BONES) {
Vector<int> b;
- b.resize(4);
- b.write[0] = barr[i * 4 + 0];
- b.write[1] = barr[i * 4 + 1];
- b.write[2] = barr[i * 4 + 2];
- b.write[3] = barr[i * 4 + 3];
+ b.resize(wcount);
+ for (int j = 0; j < wcount; j++) {
+ b.write[j] = barr[i * wcount + j];
+ }
v.bones = b;
}
if (lformat & RS::ARRAY_FORMAT_WEIGHTS) {
Vector<float> w;
- w.resize(4);
- w.write[0] = warr[i * 4 + 0];
- w.write[1] = warr[i * 4 + 1];
- w.write[2] = warr[i * 4 + 2];
- w.write[3] = warr[i * 4 + 3];
+ w.resize(wcount);
+ for (int j = 0; j < wcount; j++) {
+ w.write[j] = warr[i * wcount + j];
+ }
v.weights = w;
}
+ for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) {
+ if (lformat & custom_mask[j]) {
+ int cc = custom_float[j].size() / varr.size();
+ for (int k = 0; k < cc; k++) {
+ v.custom[j][k] = custom_float[j][i * cc + k];
+ }
+ }
+ }
+
ret.push_back(v);
}
- return ret;
-}
-
-void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, int &lformat) {
- Vector<Vector3> varr = arr[RS::ARRAY_VERTEX];
- Vector<Vector3> narr = arr[RS::ARRAY_NORMAL];
- Vector<float> tarr = arr[RS::ARRAY_TANGENT];
- Vector<Color> carr = arr[RS::ARRAY_COLOR];
- Vector<Vector2> uvarr = arr[RS::ARRAY_TEX_UV];
- Vector<Vector2> uv2arr = arr[RS::ARRAY_TEX_UV2];
- Vector<int> barr = arr[RS::ARRAY_BONES];
- Vector<float> warr = arr[RS::ARRAY_WEIGHTS];
-
- int vc = varr.size();
- if (vc == 0) {
- return;
+ if (r_format) {
+ *r_format = lformat;
}
- lformat = 0;
- if (varr.size()) {
- lformat |= RS::ARRAY_FORMAT_VERTEX;
- }
- if (narr.size()) {
- lformat |= RS::ARRAY_FORMAT_NORMAL;
- }
- if (tarr.size()) {
- lformat |= RS::ARRAY_FORMAT_TANGENT;
- }
- if (carr.size()) {
- lformat |= RS::ARRAY_FORMAT_COLOR;
- }
- if (uvarr.size()) {
- lformat |= RS::ARRAY_FORMAT_TEX_UV;
- }
- if (uv2arr.size()) {
- lformat |= RS::ARRAY_FORMAT_TEX_UV2;
- }
- if (barr.size()) {
- lformat |= RS::ARRAY_FORMAT_BONES;
- }
- if (warr.size()) {
- lformat |= RS::ARRAY_FORMAT_WEIGHTS;
- }
+ return ret;
+}
- for (int i = 0; i < vc; i++) {
- Vertex v;
- if (lformat & RS::ARRAY_FORMAT_VERTEX) {
- v.vertex = varr[i];
- }
- if (lformat & RS::ARRAY_FORMAT_NORMAL) {
- v.normal = narr[i];
- }
- if (lformat & RS::ARRAY_FORMAT_TANGENT) {
- Plane p(tarr[i * 4 + 0], tarr[i * 4 + 1], tarr[i * 4 + 2], tarr[i * 4 + 3]);
- v.tangent = p.normal;
- v.binormal = p.normal.cross(v.tangent).normalized() * p.d;
- }
- if (lformat & RS::ARRAY_FORMAT_COLOR) {
- v.color = carr[i];
- }
- if (lformat & RS::ARRAY_FORMAT_TEX_UV) {
- v.uv = uvarr[i];
- }
- if (lformat & RS::ARRAY_FORMAT_TEX_UV2) {
- v.uv2 = uv2arr[i];
- }
- if (lformat & RS::ARRAY_FORMAT_BONES) {
- Vector<int> b;
- b.resize(4);
- b.write[0] = barr[i * 4 + 0];
- b.write[1] = barr[i * 4 + 1];
- b.write[2] = barr[i * 4 + 2];
- b.write[3] = barr[i * 4 + 3];
- v.bones = b;
- }
- if (lformat & RS::ARRAY_FORMAT_WEIGHTS) {
- Vector<float> w;
- w.resize(4);
- w.write[0] = warr[i * 4 + 0];
- w.write[1] = warr[i * 4 + 1];
- w.write[2] = warr[i * 4 + 2];
- w.write[3] = warr[i * 4 + 3];
- v.weights = w;
- }
+void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, uint32_t &lformat) {
+ Vector<Vertex> arrays = create_vertex_array_from_triangle_arrays(arr, &lformat);
+ ERR_FAIL_COND(arrays.size() == 0);
- r_vertex->push_back(v);
+ for (int i = 0; i < arrays.size(); i++) {
+ r_vertex->push_back(arrays[i]);
}
//indices
@@ -725,7 +863,7 @@ void SurfaceTool::append_from(const Ref<Mesh> &p_existing, int p_surface, const
format = 0;
}
- int nformat;
+ uint32_t nformat;
List<Vertex> nvertices;
List<int> nindices;
_create_list(p_existing, p_surface, &nvertices, &nindices, nformat);
@@ -975,19 +1113,48 @@ void SurfaceTool::clear() {
vertex_array.clear();
smooth_groups.clear();
material.unref();
+ for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
+ last_custom_format[i] = CUSTOM_MAX;
+ }
+ skin_weights = SKIN_4_WEIGHTS;
+}
+
+void SurfaceTool::set_skin_weight_count(SkinWeightCount p_weights) {
+ ERR_FAIL_COND(begun);
+ skin_weights = p_weights;
+}
+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;
+}
+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];
}
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("begin", "primitive"), &SurfaceTool::begin);
ClassDB::bind_method(D_METHOD("add_vertex", "vertex"), &SurfaceTool::add_vertex);
- ClassDB::bind_method(D_METHOD("add_color", "color"), &SurfaceTool::add_color);
- ClassDB::bind_method(D_METHOD("add_normal", "normal"), &SurfaceTool::add_normal);
- ClassDB::bind_method(D_METHOD("add_tangent", "tangent"), &SurfaceTool::add_tangent);
- ClassDB::bind_method(D_METHOD("add_uv", "uv"), &SurfaceTool::add_uv);
- ClassDB::bind_method(D_METHOD("add_uv2", "uv2"), &SurfaceTool::add_uv2);
- ClassDB::bind_method(D_METHOD("add_bones", "bones"), &SurfaceTool::add_bones);
- ClassDB::bind_method(D_METHOD("add_weights", "weights"), &SurfaceTool::add_weights);
+ ClassDB::bind_method(D_METHOD("set_color", "color"), &SurfaceTool::set_color);
+ ClassDB::bind_method(D_METHOD("set_normal", "normal"), &SurfaceTool::set_normal);
+ ClassDB::bind_method(D_METHOD("set_tangent", "tangent"), &SurfaceTool::set_tangent);
+ ClassDB::bind_method(D_METHOD("set_uv", "uv"), &SurfaceTool::set_uv);
+ 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("add_smooth_group", "smooth"), &SurfaceTool::add_smooth_group);
ClassDB::bind_method(D_METHOD("add_triangle_fan", "vertices", "uvs", "colors", "uv2s", "normals", "tangents"), &SurfaceTool::add_triangle_fan, DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Color>()), DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Vector3>()), DEFVAL(Vector<Plane>()));
@@ -1006,13 +1173,29 @@ void SurfaceTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_from", "existing", "surface"), &SurfaceTool::create_from);
ClassDB::bind_method(D_METHOD("create_from_blend_shape", "existing", "surface", "blend_shape"), &SurfaceTool::create_from_blend_shape);
ClassDB::bind_method(D_METHOD("append_from", "existing", "surface", "transform"), &SurfaceTool::append_from);
- ClassDB::bind_method(D_METHOD("commit", "existing", "flags"), &SurfaceTool::commit, DEFVAL(Variant()), DEFVAL(Mesh::ARRAY_COMPRESS_DEFAULT));
+ ClassDB::bind_method(D_METHOD("commit", "existing", "flags"), &SurfaceTool::commit, DEFVAL(Variant()), DEFVAL(0));
ClassDB::bind_method(D_METHOD("commit_to_arrays"), &SurfaceTool::commit_to_arrays);
+
+ BIND_ENUM_CONSTANT(CUSTOM_RGBA8_UNORM);
+ BIND_ENUM_CONSTANT(CUSTOM_RGBA8_SNORM);
+ BIND_ENUM_CONSTANT(CUSTOM_RG_HALF);
+ BIND_ENUM_CONSTANT(CUSTOM_RGBA_HALF);
+ BIND_ENUM_CONSTANT(CUSTOM_R_FLOAT);
+ BIND_ENUM_CONSTANT(CUSTOM_RG_FLOAT);
+ BIND_ENUM_CONSTANT(CUSTOM_RGB_FLOAT);
+ BIND_ENUM_CONSTANT(CUSTOM_RGBA_FLOAT);
+ BIND_ENUM_CONSTANT(CUSTOM_MAX);
+ BIND_ENUM_CONSTANT(SKIN_4_WEIGHTS);
+ BIND_ENUM_CONSTANT(SKIN_8_WEIGHTS);
}
SurfaceTool::SurfaceTool() {
first = false;
begun = false;
+ for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
+ last_custom_format[i] = CUSTOM_MAX;
+ }
primitive = Mesh::PRIMITIVE_LINES;
+ skin_weights = SKIN_4_WEIGHTS;
format = 0;
}
diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h
index d7b255e695..4a5c7d990c 100644
--- a/scene/resources/surface_tool.h
+++ b/scene/resources/surface_tool.h
@@ -49,12 +49,30 @@ public:
Vector2 uv2;
Vector<int> bones;
Vector<float> weights;
+ Color custom[RS::ARRAY_CUSTOM_COUNT];
bool operator==(const Vertex &p_vertex) const;
Vertex() {}
};
+ enum CustomFormat {
+ CUSTOM_RGBA8_UNORM = RS::ARRAY_CUSTOM_RGBA8_UNORM,
+ CUSTOM_RGBA8_SNORM = RS::ARRAY_CUSTOM_RGBA8_SNORM,
+ CUSTOM_RG_HALF = RS::ARRAY_CUSTOM_RG_HALF,
+ CUSTOM_RGBA_HALF = RS::ARRAY_CUSTOM_RGBA_HALF,
+ CUSTOM_R_FLOAT = RS::ARRAY_CUSTOM_R_FLOAT,
+ CUSTOM_RG_FLOAT = RS::ARRAY_CUSTOM_RG_FLOAT,
+ CUSTOM_RGB_FLOAT = RS::ARRAY_CUSTOM_RGB_FLOAT,
+ CUSTOM_RGBA_FLOAT = RS::ARRAY_CUSTOM_RGBA_FLOAT,
+ CUSTOM_MAX = RS::ARRAY_CUSTOM_MAX
+ };
+
+ enum SkinWeightCount {
+ SKIN_4_WEIGHTS,
+ SKIN_8_WEIGHTS
+ };
+
private:
struct VertexHasher {
static _FORCE_INLINE_ uint32_t hash(const Vertex &p_vtx);
@@ -71,7 +89,7 @@ private:
bool begun;
bool first;
Mesh::PrimitiveType primitive;
- int format;
+ uint32_t format;
Ref<Material> material;
//arrays
List<Vertex> vertex_array;
@@ -87,8 +105,14 @@ private:
Vector<float> last_weights;
Plane last_tangent;
- void _create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, int &lformat);
- void _create_list(const Ref<Mesh> &p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index, int &lformat);
+ SkinWeightCount skin_weights;
+
+ Color last_custom[RS::ARRAY_CUSTOM_COUNT];
+
+ CustomFormat last_custom_format[RS::ARRAY_CUSTOM_COUNT];
+
+ void _create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, uint32_t &lformat);
+ void _create_list(const Ref<Mesh> &p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index, uint32_t &lformat);
//mikktspace callbacks
static int mikktGetNumFaces(const SMikkTSpaceContext *pContext);
@@ -103,18 +127,26 @@ protected:
static void _bind_methods();
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 begin(Mesh::PrimitiveType p_primitive);
+ void set_color(Color p_color);
+ void set_normal(const Vector3 &p_normal);
+ 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_bones(const Vector<int> &p_bones);
+ void set_weights(const Vector<float> &p_weights);
+
void add_vertex(const Vector3 &p_vertex);
- void add_color(Color p_color);
- void add_normal(const Vector3 &p_normal);
- void add_tangent(const Plane &p_tangent);
- void add_uv(const Vector2 &p_uv);
- void add_uv2(const Vector2 &p_uv2);
- void add_bones(const Vector<int> &p_bones);
- void add_weights(const Vector<float> &p_weights);
- void add_smooth_group(bool p_smooth);
+ void add_smooth_group(bool p_smooth);
void add_triangle_fan(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uvs = Vector<Vector2>(), const Vector<Color> &p_colors = Vector<Color>(), const Vector<Vector2> &p_uv2s = Vector<Vector2>(), const Vector<Vector3> &p_normals = Vector<Vector3>(), const Vector<Plane> &p_tangents = Vector<Plane>());
void add_index(int p_index);
@@ -131,14 +163,17 @@ public:
List<Vertex> &get_vertex_array() { return vertex_array; }
void create_from_triangle_arrays(const Array &p_arrays);
- static Vector<Vertex> create_vertex_array_from_triangle_arrays(const Array &p_arrays);
+ static Vector<Vertex> create_vertex_array_from_triangle_arrays(const Array &p_arrays, uint32_t *r_format = nullptr);
Array commit_to_arrays();
void create_from(const Ref<Mesh> &p_existing, int p_surface);
void create_from_blend_shape(const Ref<Mesh> &p_existing, int p_surface, const String &p_blend_shape_name);
void append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform &p_xform);
- Ref<ArrayMesh> commit(const Ref<ArrayMesh> &p_existing = Ref<ArrayMesh>(), uint32_t p_flags = Mesh::ARRAY_COMPRESS_DEFAULT);
+ Ref<ArrayMesh> commit(const Ref<ArrayMesh> &p_existing = Ref<ArrayMesh>(), uint32_t p_flags = 0);
SurfaceTool();
};
+VARIANT_ENUM_CAST(SurfaceTool::CustomFormat)
+VARIANT_ENUM_CAST(SurfaceTool::SkinWeightCount)
+
#endif