From 3bd0ca2a2d978a7fe43358478143a953b3f6a4b5 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 4 May 2018 09:32:40 -0300 Subject: [PATCH] Skeletal deform working --- drivers/gles3/rasterizer_canvas_gles3.cpp | 27 +++- drivers/gles3/rasterizer_canvas_gles3.h | 1 + drivers/gles3/shaders/canvas.glsl | 64 +++++---- editor/plugins/polygon_2d_editor_plugin.cpp | 149 ++++++++++++-------- editor/plugins/polygon_2d_editor_plugin.h | 4 +- 5 files changed, 147 insertions(+), 98 deletions(-) diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 12da7351bd7..b221a41893f 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -287,7 +287,8 @@ void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable, bool p_ninepat state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, state.extra_matrix); if (state.using_skeleton) { - state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TO_OBJECT_LOCAL_MATRIX, state.skeleton_transform); + state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM, state.skeleton_transform); + state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse); } if (storage->frame.current_rt) { state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); @@ -306,11 +307,17 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun uint32_t buffer_ofs = 0; //vertex +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices); glEnableVertexAttribArray(VS::ARRAY_VERTEX); glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs); buffer_ofs += sizeof(Vector2) * p_vertex_count; //color +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif if (p_singlecolor) { glDisableVertexAttribArray(VS::ARRAY_COLOR); @@ -327,6 +334,10 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun buffer_ofs += sizeof(Color) * p_vertex_count; } +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif + if (p_uvs) { glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); @@ -338,11 +349,16 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun glDisableVertexAttribArray(VS::ARRAY_TEX_UV); } +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif + if (p_bones && p_weights) { glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(int) * 4 * p_vertex_count, p_bones); glEnableVertexAttribArray(VS::ARRAY_BONES); - glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, false, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs); + //glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, false, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs); + glVertexAttribIPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs); buffer_ofs += sizeof(int) * 4 * p_vertex_count; glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(float) * 4 * p_vertex_count, p_weights); @@ -355,6 +371,10 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun glVertexAttrib4f(VS::ARRAY_WEIGHTS, 0, 0, 0, 0); } +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif + //bind the indices buffer. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices); @@ -1145,7 +1165,8 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons if (!skeleton->use_2d) { skeleton = NULL; } else { - state.skeleton_transform = ci->final_transform.affine_inverse() * (p_transform * skeleton->base_transform_2d); + state.skeleton_transform = p_transform * skeleton->base_transform_2d; + state.skeleton_transform_inverse = state.skeleton_transform.affine_inverse(); } } diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index 73a0f85bc95..bfaf1fdb4ba 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -86,6 +86,7 @@ public: Transform2D final_transform; bool using_skeleton; Transform2D skeleton_transform; + Transform2D skeleton_transform_inverse; } state; diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 910867c9b12..326aab4c7c5 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -58,7 +58,8 @@ out highp vec2 pixel_size_interp; #ifdef USE_SKELETON uniform mediump sampler2D skeleton_texture; // texunit:-1 -uniform mat4 skeleton_to_object_local_matrix; +uniform highp mat4 skeleton_transform; +uniform highp mat4 skeleton_transform_inverse; #endif #ifdef USE_LIGHTING @@ -156,6 +157,36 @@ void main() { #endif + +#define extra_matrix extra_matrix2 + +{ + +VERTEX_SHADER_CODE + +} + + +#ifdef USE_NINEPATCH + + pixel_size_interp=abs(dst_rect.zw) * vertex; +#endif + +#if !defined(SKIP_TRANSFORM_USED) + outvec = extra_matrix * outvec; + outvec = modelview_matrix * outvec; +#endif + +#undef extra_matrix + + color_interp = color; + +#ifdef USE_PIXEL_SNAP + + outvec.xy=floor(outvec+0.5).xy; +#endif + + #ifdef USE_SKELETON if (bone_weights!=vec4(0.0)){ //must be a valid bone @@ -192,42 +223,13 @@ void main() { texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0) ) * bone_weights.w; - mat4 bone_matrix = /*skeleton_to_object_local_matrix */ transpose(mat4(m[0],m[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0))); + mat4 bone_matrix = skeleton_transform * transpose(mat4(m[0],m[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0))) * skeleton_transform_inverse; outvec = bone_matrix * outvec; } #endif -#define extra_matrix extra_matrix2 - -{ - -VERTEX_SHADER_CODE - -} - - -#ifdef USE_NINEPATCH - - pixel_size_interp=abs(dst_rect.zw) * vertex; -#endif - -#if !defined(SKIP_TRANSFORM_USED) - outvec = extra_matrix * outvec; - outvec = modelview_matrix * outvec; -#endif - -#undef extra_matrix - - color_interp = color; - -#ifdef USE_PIXEL_SNAP - - outvec.xy=floor(outvec+0.5).xy; -#endif - - gl_Position = projection_matrix * outvec; #ifdef USE_LIGHTING diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 14d2550000b..f04e0a801c0 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -380,23 +380,23 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { uv_drag_from = Vector2(mb->get_position().x, mb->get_position().y); uv_drag = true; - uv_prev = node->get_uv(); + points_prev = node->get_uv(); if (uv_edit_mode[0]->is_pressed()) { //edit uv - uv_prev = node->get_uv(); + points_prev = node->get_uv(); } else { //edit polygon - uv_prev = node->get_polygon(); + points_prev = node->get_polygon(); } uv_move_current = uv_mode; if (uv_move_current == UV_MODE_CREATE) { if (!uv_create) { - uv_prev.resize(0); + points_prev.resize(0); Vector2 tuv = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y)); - uv_prev.push_back(tuv); + points_prev.push_back(tuv); uv_create_to = tuv; - uv_drag_index = 0; + point_drag_index = 0; uv_drag_from = tuv; uv_drag = true; uv_create = true; @@ -404,18 +404,18 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { uv_create_poly_prev = node->get_polygon(); uv_create_bones_prev = node->call("_get_bones"); splits_prev = node->get_splits(); - node->set_polygon(uv_prev); - node->set_uv(uv_prev); + node->set_polygon(points_prev); + node->set_uv(points_prev); } else { Vector2 tuv = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y)); - if (uv_prev.size() > 3 && tuv.distance_to(uv_prev[0]) < 8) { + if (points_prev.size() > 3 && tuv.distance_to(points_prev[0]) < 8) { undo_redo->create_action(TTR("Create Polygon & UV")); undo_redo->add_do_method(node, "set_uv", node->get_uv()); - undo_redo->add_undo_method(node, "set_uv", uv_prev); + undo_redo->add_undo_method(node, "set_uv", points_prev); undo_redo->add_do_method(node, "set_polygon", node->get_polygon()); - undo_redo->add_undo_method(node, "set_polygon", uv_prev); + undo_redo->add_undo_method(node, "set_polygon", points_prev); undo_redo->add_do_method(node, "clear_bones"); undo_redo->add_undo_method(node, "_set_bones", node->call("_get_bones")); undo_redo->add_do_method(uv_edit_draw, "update"); @@ -425,12 +425,12 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { uv_create = false; _uv_mode(UV_MODE_EDIT_POINT); } else { - uv_prev.push_back(tuv); - uv_drag_index = uv_prev.size() - 1; + points_prev.push_back(tuv); + point_drag_index = points_prev.size() - 1; uv_drag_from = tuv; } - node->set_polygon(uv_prev); - node->set_uv(uv_prev); + node->set_polygon(points_prev); + node->set_uv(points_prev); } } @@ -446,34 +446,34 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { if (uv_move_current == UV_MODE_EDIT_POINT) { - uv_drag_index = -1; - for (int i = 0; i < uv_prev.size(); i++) { + point_drag_index = -1; + for (int i = 0; i < points_prev.size(); i++) { - Vector2 tuv = mtx.xform(uv_prev[i]); + Vector2 tuv = mtx.xform(points_prev[i]); if (tuv.distance_to(Vector2(mb->get_position().x, mb->get_position().y)) < 8) { uv_drag_from = tuv; - uv_drag_index = i; + point_drag_index = i; } } - if (uv_drag_index == -1) { + if (point_drag_index == -1) { uv_drag = false; } } if (uv_move_current == UV_MODE_ADD_SPLIT) { - int drag_index = -1; - drag_index = -1; - for (int i = 0; i < uv_prev.size(); i++) { + int split_to_index = -1; + split_to_index = -1; + for (int i = 0; i < points_prev.size(); i++) { - Vector2 tuv = mtx.xform(uv_prev[i]); + Vector2 tuv = mtx.xform(points_prev[i]); if (tuv.distance_to(Vector2(mb->get_position().x, mb->get_position().y)) < 8) { - drag_index = i; + split_to_index = i; } } - if (drag_index == -1) { + if (split_to_index == -1) { split_create = false; return; } @@ -481,41 +481,65 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { if (split_create) { split_create = false; - if (drag_index < uv_drag_index) { - SWAP(drag_index, uv_drag_index); + if (split_to_index < point_drag_index) { + SWAP(split_to_index, point_drag_index); } bool valid = true; - if (drag_index == uv_drag_index) { + String split_error; + if (split_to_index == point_drag_index) { + split_error = TTR("Split point with itself."); valid = false; } - if (drag_index + 1 == uv_drag_index) { + if (split_to_index + 1 == point_drag_index) { //not a split,goes along the edge + split_error = TTR("Split can't form an existing edge."); valid = false; } - if (drag_index == uv_prev.size() - 1 && uv_drag_index == 0) { + if (split_to_index == points_prev.size() - 1 && point_drag_index == 0) { //not a split,goes along the edge + split_error = TTR("Split can't form an existing edge."); valid = false; } + for (int i = 0; i < splits_prev.size(); i += 2) { - if (splits_prev[i] == uv_drag_index && splits_prev[i + 1] == drag_index) { + + if (splits_prev[i] == point_drag_index && splits_prev[i + 1] == split_to_index) { //already exists + split_error = TTR("Split already exists."); valid = false; - } - if (splits_prev[i] > uv_drag_index && splits_prev[i + 1] > drag_index) { - //crossing - valid = false; + break; } - if (splits_prev[i] < uv_drag_index && splits_prev[i + 1] < drag_index) { - //crossing opposite direction + int a_state; //-1, outside split, 0 split point, +1, inside split + if (point_drag_index == splits_prev[i] || point_drag_index == splits_prev[i + 1]) { + a_state = 0; + } else if (point_drag_index < splits_prev[i] || point_drag_index > splits_prev[i + 1]) { + a_state = -1; + } else { + a_state = 1; + } + + int b_state; //-1, outside split, 0 split point, +1, inside split + if (split_to_index == splits_prev[i] || split_to_index == splits_prev[i + 1]) { + b_state = 0; + } else if (split_to_index < splits_prev[i] || split_to_index > splits_prev[i + 1]) { + b_state = -1; + } else { + b_state = 1; + } + + if (b_state * a_state < 0) { + //crossing + split_error = "Split crosses another split."; valid = false; + break; } } if (valid) { - splits_prev.push_back(uv_drag_index); - splits_prev.push_back(drag_index); + splits_prev.push_back(point_drag_index); + splits_prev.push_back(split_to_index); undo_redo->create_action(TTR("Add Split")); @@ -525,13 +549,14 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->commit_action(); } else { - error->set_text(TTR("Invalid Split")); + error->set_text(TTR("Invalid Split: ") + split_error); error->popup_centered_minsize(); } } else { - uv_drag_index = drag_index; + point_drag_index = split_to_index; split_create = true; + splits_prev = node->get_splits(); uv_create_to = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y)); } } @@ -539,11 +564,11 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { if (uv_move_current == UV_MODE_REMOVE_SPLIT) { for (int i = 0; i < splits_prev.size(); i += 2) { - if (splits_prev[i] < 0 || splits_prev[i] >= uv_prev.size()) + if (splits_prev[i] < 0 || splits_prev[i] >= points_prev.size()) continue; - if (splits_prev[i + 1] < 0 || splits_prev[i] >= uv_prev.size()) + if (splits_prev[i + 1] < 0 || splits_prev[i] >= points_prev.size()) continue; - Vector2 e[2] = { mtx.xform(uv_prev[splits_prev[i]]), mtx.xform(uv_prev[splits_prev[i + 1]]) }; + Vector2 e[2] = { mtx.xform(points_prev[splits_prev[i]]), mtx.xform(points_prev[splits_prev[i + 1]]) }; Vector2 mp = Vector2(mb->get_position().x, mb->get_position().y); Vector2 cp = Geometry::get_closest_point_to_segment_2d(mp, e); if (cp.distance_to(mp) < 8) { @@ -574,7 +599,7 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { } } - if (bone_selected != -1 && node->get_bone_weights(bone_selected).size() == uv_prev.size()) { + if (bone_selected != -1 && node->get_bone_weights(bone_selected).size() == points_prev.size()) { prev_weights = node->get_bone_weights(bone_selected); bone_painting = true; @@ -588,10 +613,10 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { if (uv_edit_mode[0]->is_pressed()) { //edit uv undo_redo->add_do_method(node, "set_uv", node->get_uv()); - undo_redo->add_undo_method(node, "set_uv", uv_prev); + undo_redo->add_undo_method(node, "set_uv", points_prev); } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon undo_redo->add_do_method(node, "set_polygon", node->get_polygon()); - undo_redo->add_undo_method(node, "set_polygon", uv_prev); + undo_redo->add_undo_method(node, "set_polygon", points_prev); } undo_redo->add_do_method(uv_edit_draw, "update"); undo_redo->add_undo_method(uv_edit_draw, "update"); @@ -624,9 +649,9 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { uv_drag = false; if (uv_edit_mode[0]->is_pressed()) { //edit uv - node->set_uv(uv_prev); + node->set_uv(points_prev); } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon - node->set_polygon(uv_prev); + node->set_polygon(points_prev); } uv_edit_draw->update(); } else if (split_create) { @@ -669,8 +694,8 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { } break; case UV_MODE_EDIT_POINT: { - PoolVector uv_new = uv_prev; - uv_new.set(uv_drag_index, uv_new[uv_drag_index] + drag); + PoolVector uv_new = points_prev; + uv_new.set(point_drag_index, uv_new[point_drag_index] + drag); if (uv_edit_mode[0]->is_pressed()) { //edit uv node->set_uv(uv_new); @@ -680,7 +705,7 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { } break; case UV_MODE_MOVE: { - PoolVector uv_new = uv_prev; + PoolVector uv_new = points_prev; for (int i = 0; i < uv_new.size(); i++) uv_new.set(i, uv_new[i] + drag); @@ -694,16 +719,16 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { case UV_MODE_ROTATE: { Vector2 center; - PoolVector uv_new = uv_prev; + PoolVector uv_new = points_prev; for (int i = 0; i < uv_new.size(); i++) - center += uv_prev[i]; + center += points_prev[i]; center /= uv_new.size(); float angle = (uv_drag_from - mtx.xform(center)).normalized().angle_to((uv_drag_to - mtx.xform(center)).normalized()); for (int i = 0; i < uv_new.size(); i++) { - Vector2 rel = uv_prev[i] - center; + Vector2 rel = points_prev[i] - center; rel = rel.rotated(angle); uv_new.set(i, center + rel); } @@ -718,10 +743,10 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { case UV_MODE_SCALE: { Vector2 center; - PoolVector uv_new = uv_prev; + PoolVector uv_new = points_prev; for (int i = 0; i < uv_new.size(); i++) - center += uv_prev[i]; + center += points_prev[i]; center /= uv_new.size(); float from_dist = uv_drag_from.distance_to(mtx.xform(center)); @@ -732,7 +757,7 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { float scale = to_dist / from_dist; for (int i = 0; i < uv_new.size(); i++) { - Vector2 rel = uv_prev[i] - center; + Vector2 rel = points_prev[i] - center; rel = rel * scale; uv_new.set(i, center + rel); } @@ -760,7 +785,7 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { PoolVector::Write w = painted_weights.write(); PoolVector::Read r = prev_weights.read(); - PoolVector::Read rv = uv_prev.read(); + PoolVector::Read rv = points_prev.read(); for (int i = 0; i < pc; i++) { if (mtx.xform(rv[i]).distance_to(bone_paint_pos) < radius) { @@ -899,7 +924,7 @@ void Polygon2DEditor::_uv_draw() { } if (split_create) { - Vector2 from = uvs[uv_drag_index]; + Vector2 from = uvs[point_drag_index]; Vector2 to = uv_create_to; uv_edit_draw->draw_line(mtx.xform(from), mtx.xform(to), Color(0.9, 0.5, 0.5), 2); } @@ -1232,7 +1257,7 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_edit_draw->connect("draw", this, "_uv_draw"); uv_edit_draw->connect("gui_input", this, "_uv_input"); uv_draw_zoom = 1.0; - uv_drag_index = -1; + point_drag_index = -1; uv_drag = false; uv_create = false; updating_uv_scroll = false; diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index cf529b39f77..f9b42a21c2b 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -99,14 +99,14 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { Vector2 uv_draw_ofs; float uv_draw_zoom; - PoolVector uv_prev; + PoolVector points_prev; PoolVector uv_create_uv_prev; PoolVector uv_create_poly_prev; Array uv_create_bones_prev; PoolVector splits_prev; Vector2 uv_create_to; - int uv_drag_index; + int point_drag_index; bool uv_drag; bool uv_create; bool split_create;