This commit is contained in:
ocornut 2015-07-30 21:37:59 -06:00
parent c639f65eb7
commit a7e5945206
1 changed files with 110 additions and 42 deletions

View File

@ -268,6 +268,7 @@ void ImDrawList::PopTextureID()
UpdateTextureID(); UpdateTextureID();
} }
// NB: this can be called with negative count for removing primitives (as long as the result does not underflow)
void ImDrawList::PrimReserve(int idx_count, int vtx_count) void ImDrawList::PrimReserve(int idx_count, int vtx_count)
{ {
ImDrawCmd& draw_cmd = CmdBuffer.Data[CmdBuffer.Size-1]; ImDrawCmd& draw_cmd = CmdBuffer.Data[CmdBuffer.Size-1];
@ -315,6 +316,7 @@ void ImDrawList::PrimRectUV(const ImVec2& a, const ImVec2& c, const ImVec2& uv_a
_IdxWritePtr += 6; _IdxWritePtr += 6;
} }
// TODO: Thickness anti-aliased lines cap are missing their AA fringe.
void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, bool closed, float thickness, bool anti_aliased) void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, bool closed, float thickness, bool anti_aliased)
{ {
if (points_count < 2) if (points_count < 2)
@ -328,18 +330,20 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
if (!closed) if (!closed)
count = points_count-1; count = points_count-1;
if (anti_aliased && thickness == 1.0f) const bool thick_line = thickness > 1.0f;
if (anti_aliased)
{ {
// Anti-aliased stroke // Anti-aliased stroke
const float AA_SIZE = 1.0f; const float AA_SIZE = 1.0f;
const ImU32 col_trans = col & 0x00ffffff; const ImU32 col_trans = col & 0x00ffffff;
const int idx_count = count*12;
const int vtx_count = points_count*3; const int idx_count = thick_line ? count*18 : count*12;
const int vtx_count = thick_line ? points_count*4 : points_count*3;
PrimReserve(idx_count, vtx_count); PrimReserve(idx_count, vtx_count);
// Temporary buffer // Temporary buffer
ImVec2* temp_points = (ImVec2*)alloca(points_count * 3 * sizeof(ImVec2)); ImVec2* temp_normals = (ImVec2*)alloca(points_count * (thick_line ? 5 : 3) * sizeof(ImVec2));
ImVec2* temp_normals = temp_points + points_count * 2; ImVec2* temp_points = temp_normals + points_count;
for (int i1 = 0; i1 < count; i1++) for (int i1 = 0; i1 < count; i1++)
{ {
@ -349,53 +353,117 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
temp_normals[i1].x = diff.y; temp_normals[i1].x = diff.y;
temp_normals[i1].y = -diff.x; temp_normals[i1].y = -diff.x;
} }
if (!closed) if (!closed)
{
temp_normals[points_count-1] = temp_normals[points_count-2]; temp_normals[points_count-1] = temp_normals[points_count-2];
temp_points[0] = points[0] + temp_normals[0] * AA_SIZE;
temp_points[1] = points[0] - temp_normals[0] * AA_SIZE;
temp_points[(points_count-1)*2+0] = points[points_count-1] + temp_normals[points_count-1] * AA_SIZE;
temp_points[(points_count-1)*2+1] = points[points_count-1] - temp_normals[points_count-1] * AA_SIZE;
}
// FIXME-OPT: Merge the different loops, possibly remove the temporary buffer. if (!thick_line)
unsigned int idx1 = _VtxCurrentIdx;
for (int i1 = 0; i1 < count; i1++)
{ {
const int i2 = (i1+1) == points_count ? 0 : i1+1; if (!closed)
unsigned int idx2 = (i1+1) == points_count ? _VtxCurrentIdx : idx1+3;
// Average normals
ImVec2 dm = (temp_normals[i1] + temp_normals[i2]) * 0.5f;
float dmr2 = dm.x*dm.x + dm.y*dm.y;
if (dmr2 > 0.000001f)
{ {
float scale = 1.0f / dmr2; temp_points[0] = points[0] + temp_normals[0] * AA_SIZE;
if (scale > 100.0f) scale = 100.0f; temp_points[1] = points[0] - temp_normals[0] * AA_SIZE;
dm *= scale; temp_points[(points_count-1)*2+0] = points[points_count-1] + temp_normals[points_count-1] * AA_SIZE;
temp_points[(points_count-1)*2+1] = points[points_count-1] - temp_normals[points_count-1] * AA_SIZE;
} }
dm *= AA_SIZE;
temp_points[i2*2+0] = points[i2] + dm;
temp_points[i2*2+1] = points[i2] - dm;
// Add indexes // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer.
_IdxWritePtr[0] = (ImDrawIdx)(idx2+0); _IdxWritePtr[1] = (ImDrawIdx)(idx1+0); _IdxWritePtr[2] = (ImDrawIdx)(idx1+2); unsigned int idx1 = _VtxCurrentIdx;
_IdxWritePtr[3] = (ImDrawIdx)(idx1+2); _IdxWritePtr[4] = (ImDrawIdx)(idx2+2); _IdxWritePtr[5] = (ImDrawIdx)(idx2+0); for (int i1 = 0; i1 < count; i1++)
_IdxWritePtr[6] = (ImDrawIdx)(idx2+1); _IdxWritePtr[7] = (ImDrawIdx)(idx1+1); _IdxWritePtr[8] = (ImDrawIdx)(idx1+0); {
_IdxWritePtr[9] = (ImDrawIdx)(idx1+0); _IdxWritePtr[10]= (ImDrawIdx)(idx2+0); _IdxWritePtr[11]= (ImDrawIdx)(idx2+1); const int i2 = (i1+1) == points_count ? 0 : i1+1;
_IdxWritePtr += 12; unsigned int idx2 = (i1+1) == points_count ? _VtxCurrentIdx : idx1+3;
idx1 = idx2; // Average normals
ImVec2 dm = (temp_normals[i1] + temp_normals[i2]) * 0.5f;
float dmr2 = dm.x*dm.x + dm.y*dm.y;
if (dmr2 > 0.000001f)
{
float scale = 1.0f / dmr2;
if (scale > 100.0f) scale = 100.0f;
dm *= scale;
}
dm *= AA_SIZE;
temp_points[i2*2+0] = points[i2] + dm;
temp_points[i2*2+1] = points[i2] - dm;
// Add indexes
_IdxWritePtr[0] = (ImDrawIdx)(idx2+0); _IdxWritePtr[1] = (ImDrawIdx)(idx1+0); _IdxWritePtr[2] = (ImDrawIdx)(idx1+2);
_IdxWritePtr[3] = (ImDrawIdx)(idx1+2); _IdxWritePtr[4] = (ImDrawIdx)(idx2+2); _IdxWritePtr[5] = (ImDrawIdx)(idx2+0);
_IdxWritePtr[6] = (ImDrawIdx)(idx2+1); _IdxWritePtr[7] = (ImDrawIdx)(idx1+1); _IdxWritePtr[8] = (ImDrawIdx)(idx1+0);
_IdxWritePtr[9] = (ImDrawIdx)(idx1+0); _IdxWritePtr[10]= (ImDrawIdx)(idx2+0); _IdxWritePtr[11]= (ImDrawIdx)(idx2+1);
_IdxWritePtr += 12;
idx1 = idx2;
}
// Add vertexes
for (int i = 0; i < points_count; i++)
{
_VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;
_VtxWritePtr[1].pos = temp_points[i*2+0]; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans;
_VtxWritePtr[2].pos = temp_points[i*2+1]; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col_trans;
_VtxWritePtr += 3;
}
} }
else
// Add vertexes
for (int i = 0; i < points_count; i++)
{ {
_VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
_VtxWritePtr[1].pos = temp_points[i*2+0]; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans; if (!closed)
_VtxWritePtr[2].pos = temp_points[i*2+1]; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col_trans; {
_VtxWritePtr += 3; temp_points[0] = points[0] + temp_normals[0] * (half_inner_thickness + AA_SIZE);
temp_points[1] = points[0] + temp_normals[0] * (half_inner_thickness);
temp_points[2] = points[0] - temp_normals[0] * (half_inner_thickness);
temp_points[3] = points[0] - temp_normals[0] * (half_inner_thickness + AA_SIZE);
temp_points[(points_count-1)*4+0] = points[points_count-1] + temp_normals[points_count-1] * (half_inner_thickness + AA_SIZE);
temp_points[(points_count-1)*4+1] = points[points_count-1] + temp_normals[points_count-1] * (half_inner_thickness);
temp_points[(points_count-1)*4+2] = points[points_count-1] - temp_normals[points_count-1] * (half_inner_thickness);
temp_points[(points_count-1)*4+3] = points[points_count-1] - temp_normals[points_count-1] * (half_inner_thickness + AA_SIZE);
}
// FIXME-OPT: Merge the different loops, possibly remove the temporary buffer.
unsigned int idx1 = _VtxCurrentIdx;
for (int i1 = 0; i1 < count; i1++)
{
const int i2 = (i1+1) == points_count ? 0 : i1+1;
unsigned int idx2 = (i1+1) == points_count ? _VtxCurrentIdx : idx1+4;
// Average normals
ImVec2 dm = (temp_normals[i1] + temp_normals[i2]) * 0.5f;
float dmr2 = dm.x*dm.x + dm.y*dm.y;
if (dmr2 > 0.000001f)
{
float scale = 1.0f / dmr2;
if (scale > 100.0f) scale = 100.0f;
dm *= scale;
}
ImVec2 dm_out = dm * (half_inner_thickness + AA_SIZE);
ImVec2 dm_in = dm * half_inner_thickness;
temp_points[i2*4+0] = points[i2] + dm_out;
temp_points[i2*4+1] = points[i2] + dm_in;
temp_points[i2*4+2] = points[i2] - dm_in;
temp_points[i2*4+3] = points[i2] - dm_out;
// Add indexes
_IdxWritePtr[0] = (ImDrawIdx)(idx2+1); _IdxWritePtr[1] = (ImDrawIdx)(idx1+1); _IdxWritePtr[2] = (ImDrawIdx)(idx1+2);
_IdxWritePtr[3] = (ImDrawIdx)(idx1+2); _IdxWritePtr[4] = (ImDrawIdx)(idx2+2); _IdxWritePtr[5] = (ImDrawIdx)(idx2+1);
_IdxWritePtr[6] = (ImDrawIdx)(idx2+1); _IdxWritePtr[7] = (ImDrawIdx)(idx1+1); _IdxWritePtr[8] = (ImDrawIdx)(idx1+0);
_IdxWritePtr[9] = (ImDrawIdx)(idx1+0); _IdxWritePtr[10] = (ImDrawIdx)(idx2+0); _IdxWritePtr[11] = (ImDrawIdx)(idx2+1);
_IdxWritePtr[12] = (ImDrawIdx)(idx2+2); _IdxWritePtr[13] = (ImDrawIdx)(idx1+2); _IdxWritePtr[14] = (ImDrawIdx)(idx1+3);
_IdxWritePtr[15] = (ImDrawIdx)(idx1+3); _IdxWritePtr[16] = (ImDrawIdx)(idx2+3); _IdxWritePtr[17] = (ImDrawIdx)(idx2+2);
_IdxWritePtr += 18;
idx1 = idx2;
}
// Add vertexes
for (int i = 0; i < points_count; i++)
{
_VtxWritePtr[0].pos = temp_points[i*4+0]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col_trans;
_VtxWritePtr[1].pos = temp_points[i*4+1]; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col;
_VtxWritePtr[2].pos = temp_points[i*4+2]; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col;
_VtxWritePtr[3].pos = temp_points[i*4+3]; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col_trans;
_VtxWritePtr += 4;
}
} }
_VtxCurrentIdx += (ImDrawIdx)vtx_count; _VtxCurrentIdx += (ImDrawIdx)vtx_count;
} }