diff --git a/imgui_draw.cpp b/imgui_draw.cpp index fe949da041f3..944e3133a9ad 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -800,6 +800,10 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun { const ImVec2 uv = _Data->TexUvWhitePixel; + if (points_count < 2) { + return; + } + if (Flags & ImDrawListFlags_AntiAliasedFill) { // Anti-aliased Fill @@ -809,32 +813,19 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun const int vtx_count = (points_count*2); PrimReserve(idx_count, vtx_count); - // Add indexes for fill - unsigned int vtx_inner_idx = _VtxCurrentIdx; - unsigned int vtx_outer_idx = _VtxCurrentIdx+1; - for (int i = 2; i < points_count; i++) - { - _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx+((i-1)<<1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx+(i<<1)); - _IdxWritePtr += 3; - } + const ImDrawIdx common_idx = (ImDrawIdx)_VtxCurrentIdx; + ImVec2 n0 = points[0] - points[points_count - 1]; + n0 *= ImInvLength(n0, 1.0f); + n0 = ImVec2(n0.y, -n0.x); - // Compute normals - ImVec2* temp_normals = (ImVec2*)alloca(points_count * sizeof(ImVec2)); - for (int i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) - { - const ImVec2& p0 = points[i0]; - const ImVec2& p1 = points[i1]; - ImVec2 diff = p1 - p0; - diff *= ImInvLength(diff, 1.0f); - temp_normals[i0].x = diff.y; - temp_normals[i0].y = -diff.x; - } + for (int i = 0; i < points_count; i++) { + const ImVec2& current = points[i]; + const ImVec2& next = points[(i + 1) % points_count]; + + ImVec2 n1 = next - current; + n1 *= ImInvLength(n1, 1.0f); + n1 = ImVec2(n1.y, -n1.x); - for (int i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) - { - // Average normals - const ImVec2& n0 = temp_normals[i0]; - const ImVec2& n1 = temp_normals[i1]; ImVec2 dm = (n0 + n1) * 0.5f; float dmr2 = dm.x*dm.x + dm.y*dm.y; if (dmr2 > 0.000001f) @@ -844,18 +835,34 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun dm *= scale; } dm *= AA_SIZE * 0.5f; + n0 = n1; - // Add vertices - _VtxWritePtr[0].pos = (points[i1] - dm); _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; // Inner - _VtxWritePtr[1].pos = (points[i1] + dm); _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans; // Outer + // 2 vertices + _VtxWritePtr[0].pos = current - dm; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; // Inner + _VtxWritePtr[1].pos = current + dm; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans; // Outer _VtxWritePtr += 2; - // Add indexes for fringes - _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx+(i1<<1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx+(i0<<1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx+(i0<<1)); - _IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx+(i0<<1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx+(i1<<1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx+(i1<<1)); + // 2 triangles for border + // Order: + // [0] +0 [1] +1 [2] +2 + // [3] +1 [4] +2 [5] +3 + _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx + 0); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + 1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + 2); + _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx + 1); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx + 2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx + 3); _IdxWritePtr += 6; + + // Maybe 1 triangle for fill + if (i >= 2) { + _IdxWritePtr[0] = common_idx; _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx-2); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx); + _IdxWritePtr += 3; + } + + _VtxCurrentIdx += 2; } - _VtxCurrentIdx += (ImDrawIdx)vtx_count; + + // Patch last indices to point to 1st iteration vertices + _IdxWritePtr[2-6] = common_idx; + _IdxWritePtr[4-6] = common_idx; + _IdxWritePtr[5-6] = common_idx + 1; } else {