From 62aad81999409fea0c5ac1db560e55e00fffbe76 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 9 Oct 2024 12:55:17 +0200 Subject: [PATCH] [godot] Fix rendering in GDExtension. --- .../example-v4-extension/project.godot | 2 +- spine-godot/spine_godot/SpineSprite.cpp | 60 +++++++++++++++++-- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/spine-godot/example-v4-extension/project.godot b/spine-godot/example-v4-extension/project.godot index d0545dcce..26b85fd71 100644 --- a/spine-godot/example-v4-extension/project.godot +++ b/spine-godot/example-v4-extension/project.godot @@ -11,7 +11,7 @@ config_version=5 [application] config/name="spine-godot-examples" -run/main_scene="res://examples/08-animation-player/animation-player.tscn" +run/main_scene="res://examples/01-helloworld/helloworld.tscn" config/features=PackedStringArray("4.3") run/low_processor_mode=true config/icon="res://icon.png" diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/spine_godot/SpineSprite.cpp index d9df6f94e..5ffa7d5db 100644 --- a/spine-godot/spine_godot/SpineSprite.cpp +++ b/spine-godot/spine_godot/SpineSprite.cpp @@ -211,15 +211,67 @@ void SpineMesh2D::update_mesh(const PackedVector2Array &vertices, const PackedColorArray &colors, const PackedInt32Array &indices, SpineRendererObject *renderer_object) { + if (!mesh.is_valid() || vertices.size() != num_vertices || indices.size() != num_indices || indices_changed) { + if (mesh.is_valid()) { + RS::get_singleton()->free_rid(mesh); + } + mesh = RS::get_singleton()->mesh_create(); + Array arrays; + arrays.resize(Mesh::ARRAY_MAX); + arrays[Mesh::ARRAY_VERTEX] = vertices; + arrays[Mesh::ARRAY_TEX_UV] = uvs; + arrays[Mesh::ARRAY_COLOR] = colors; + arrays[Mesh::ARRAY_INDEX] = indices; + RS::get_singleton()->mesh_add_surface_from_arrays(mesh, RS::PrimitiveType::PRIMITIVE_TRIANGLES, arrays, Array(), Dictionary(), RS::ArrayFormat::ARRAY_FLAG_USE_DYNAMIC_UPDATE); + Dictionary surface = RS::get_singleton()->mesh_get_surface(mesh, 0); + RS::ArrayFormat surface_format = (RS::ArrayFormat)static_cast(surface["format"]); + surface_offsets[RS::ARRAY_VERTEX] = RS::get_singleton()->mesh_surface_get_format_offset(surface_format, vertices.size(), RS::ARRAY_VERTEX); + surface_offsets[RS::ARRAY_COLOR] = RS::get_singleton()->mesh_surface_get_format_offset(surface_format, vertices.size(), RS::ARRAY_COLOR); + surface_offsets[RS::ARRAY_TEX_UV] = RS::get_singleton()->mesh_surface_get_format_offset(surface_format, vertices.size(), RS::ARRAY_TEX_UV); + vertex_stride = RS::get_singleton()->mesh_surface_get_format_vertex_stride(surface_format, vertices.size()); + attribute_stride = RS::get_singleton()->mesh_surface_get_format_attribute_stride(surface_format, vertices.size()); + num_vertices = vertices.size(); + num_indices = indices.size(); + vertex_buffer = surface["vertex_data"]; + attribute_buffer = surface["attribute_data"]; + indices_changed = false; + } else { + AABB aabb_new; + uint8_t color[4] = { + uint8_t(CLAMP(colors[0].r * 255.0, 0.0, 255.0)), + uint8_t(CLAMP(colors[0].g * 255.0, 0.0, 255.0)), + uint8_t(CLAMP(colors[0].b * 255.0, 0.0, 255.0)), + uint8_t(CLAMP(colors[0].a * 255.0, 0.0, 255.0))}; + + uint8_t *vertex_write_buffer = vertex_buffer.ptrw(); + uint8_t *attribute_write_buffer = attribute_buffer.ptrw(); + for (int i = 0; i < vertices.size(); i++) { + Vector2 vertex(vertices[i]); + if (i == 0) { + aabb_new.position = Vector3(vertex.x, vertex.y, 0); + aabb_new.size = Vector3(); + } else { + aabb_new.expand_to(Vector3(vertex.x, vertex.y, 0)); + } + + float uv[2] = {(float) uvs[i].x, (float) uvs[i].y}; + memcpy(&vertex_write_buffer[i * vertex_stride + surface_offsets[RS::ARRAY_VERTEX]], &vertex, sizeof(float) * 2); + memcpy(&attribute_write_buffer[i * attribute_stride + surface_offsets[RS::ARRAY_COLOR]], color, 4); + memcpy(&attribute_write_buffer[i * attribute_stride + surface_offsets[RS::ARRAY_TEX_UV]], uv, 8); + } + RS::get_singleton()->mesh_surface_update_vertex_region(mesh, 0, 0, vertex_buffer); + RS::get_singleton()->mesh_surface_update_attribute_region(mesh, 0, 0, attribute_buffer); + RS::get_singleton()->mesh_set_custom_aabb(mesh, aabb_new); + } + + RenderingServer::get_singleton()->canvas_item_add_mesh(this->get_canvas_item(), mesh, Transform2D(), Color(1, 1, 1, 1), renderer_object->canvas_texture->get_rid()); +} #else void SpineMesh2D::update_mesh(const Vector &vertices, const Vector &uvs, const Vector &colors, const Vector &indices, SpineRendererObject *renderer_object) { -#endif -#if SPINE_GODOT_EXTENSION -#else #if VERSION_MAJOR > 3 if (!mesh.is_valid() || vertices.size() != num_vertices || indices.size() != num_indices || indices_changed) { if (mesh.is_valid()) { @@ -339,8 +391,8 @@ void SpineMesh2D::update_mesh(const Vector &vertices, renderer_object->texture.is_null() ? RID() : renderer_object->texture->get_rid(), renderer_object->normal_map.is_null() ? RID() : renderer_object->normal_map->get_rid()); #endif -#endif } +#endif void SpineSprite::_bind_methods() { ClassDB::bind_method(D_METHOD("set_skeleton_data_res", "skeleton_data_res"), &SpineSprite::set_skeleton_data_res);