AA branch: Test disabling aa at runtime for stroke and fill.

This commit is contained in:
ocornut 2015-04-09 22:31:26 +01:00
parent 431e391ccd
commit 1e69175403
2 changed files with 185 additions and 124 deletions

305
imgui.cpp
View File

@ -7,8 +7,8 @@
// ANTI-ALIASED PRIMITIVES BRANCH
// TODO
// - settle on where to the 0.5f offset for lines
// - checkbox, slider grabs are not centered properly if you enable border (relate to point above)
// - thick lines? recently been added to the ImDrawList API as a convenience.
// - check-box, slider grabs are not centered properly if you enable border (relate to point above)
// - support for thickness stroking. recently been added to the ImDrawList API as a convenience.
/*
@ -398,6 +398,7 @@
#include <new> // new (ptr)
#ifdef _MSC_VER
#pragma warning (disable: 4127) // conditional expression is constant
#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
#endif
@ -7723,18 +7724,14 @@ void ImDrawList::PrimRectUV(const ImVec2& a, const ImVec2& c, const ImVec2& uv_a
static ImVector<ImVec2> GTempPolyData;
void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, bool closed)
void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, float thickness, bool closed)
{
(void)thickness; // Unsupported
if (points_count < 2)
return;
const float aa_size = 1.0f;
// Temporary buffer
GTempPolyData.resize(points_count * 3);
ImVec2* temp_inner = &GTempPolyData[0];
ImVec2* temp_outer = &GTempPolyData[points_count];
ImVec2* temp_normals = &GTempPolyData[points_count * 2];
const ImVec2 uv = GImGui->FontTexUvWhitePixel;
int start = 0, count = points_count;
if (!closed)
@ -7743,136 +7740,200 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
count = points_count-1;
}
for (int i = 0; i < count; i++)
const bool aa_enabled = true;//!ImGui::GetIO().KeyCtrl;
if (aa_enabled)
{
const int ni = (i+1) < points_count ? i+1 : 0;
const ImVec2& v0 = points[i];
const ImVec2& v1 = points[ni];
ImVec2 diff = v1 - v0;
float d = ImLengthSqr(diff);
if (d > 0)
diff *= 1.0f/sqrtf(d);
temp_normals[i].x = diff.y;
temp_normals[i].y = -diff.x;
}
// Anti-aliased stroke
const float aa_size = 1.0f;
if (!closed)
{
temp_normals[points_count-1] = temp_normals[points_count-2];
temp_outer[0] = points[0] + temp_normals[0]*aa_size;
temp_inner[0] = points[0] - temp_normals[0]*aa_size;
temp_outer[points_count-1] = points[points_count-1] + temp_normals[points_count-1]*aa_size;
temp_inner[points_count-1] = points[points_count-1] - temp_normals[points_count-1]*aa_size;
}
// Temporary buffer
GTempPolyData.resize(points_count * 3);
ImVec2* temp_inner = &GTempPolyData[0];
ImVec2* temp_outer = &GTempPolyData[points_count];
ImVec2* temp_normals = &GTempPolyData[points_count * 2];
for (int i = start; i < count; i++)
{
const int ni = (i+1) < points_count ? i+1 : 0;
const ImVec2& dl0 = temp_normals[i];
const ImVec2& dl1 = temp_normals[ni];
ImVec2 dm = (dl0 + dl1) * 0.5f;
float dmr2 = dm.x*dm.x + dm.y*dm.y;
if (dmr2 > 0.000001f)
for (int i = 0; i < count; i++)
{
float scale = 1.0f / dmr2;
if (scale > 100.0f) scale = 100.0f;
dm *= scale;
const int ni = (i+1) < points_count ? i+1 : 0;
const ImVec2& v0 = points[i];
const ImVec2& v1 = points[ni];
ImVec2 diff = v1 - v0;
float d = ImLengthSqr(diff);
if (d > 0)
diff *= 1.0f/sqrtf(d);
temp_normals[i].x = diff.y;
temp_normals[i].y = -diff.x;
}
if (!closed)
{
temp_normals[points_count-1] = temp_normals[points_count-2];
temp_outer[0] = points[0] + temp_normals[0]*aa_size;
temp_inner[0] = points[0] - temp_normals[0]*aa_size;
temp_outer[points_count-1] = points[points_count-1] + temp_normals[points_count-1]*aa_size;
temp_inner[points_count-1] = points[points_count-1] - temp_normals[points_count-1]*aa_size;
}
for (int i = start; i < count; i++)
{
const int ni = (i+1) < points_count ? i+1 : 0;
const ImVec2& dl0 = temp_normals[i];
const ImVec2& dl1 = temp_normals[ni];
ImVec2 dm = (dl0 + dl1) * 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_outer[ni] = points[ni] + dm;
temp_inner[ni] = points[ni] - dm;
}
const ImU32 col_trans = col & 0x00ffffff;
const int vertex_count = count*12;
PrimReserve(vertex_count);
// Stroke
for (int i = 0; i < count; i++)
{
const int ni = (i+1) < points_count ? i+1 : 0;
PrimVtx(points[ni], uv, col);
PrimVtx(points[i], uv, col);
PrimVtx(temp_outer[i], uv, col_trans);
PrimVtx(temp_outer[i], uv, col_trans);
PrimVtx(temp_outer[ni], uv, col_trans);
PrimVtx(points[ni], uv, col);
PrimVtx(temp_inner[ni], uv, col_trans);
PrimVtx(temp_inner[i], uv, col_trans);
PrimVtx(points[i], uv, col);
PrimVtx(points[i], uv, col);
PrimVtx(points[ni], uv, col);
PrimVtx(temp_inner[ni], uv, col_trans);
}
dm *= aa_size;
temp_outer[ni] = points[ni] + dm;
temp_inner[ni] = points[ni] - dm;
}
const ImU32 col_trans = col & 0x00ffffff;
const ImVec2 uv = GImGui->FontTexUvWhitePixel;
const int vertex_count = count*12;
PrimReserve(vertex_count);
// Stroke
for (int i = 0; i < count; i++)
else
{
const int ni = (i+1) < points_count ? i+1 : 0;
PrimVtx(points[ni], uv, col);
PrimVtx(points[i], uv, col);
PrimVtx(temp_outer[i], uv, col_trans);
// Non Anti-aliased Stroke
const int vertex_count = count*6;
PrimReserve(vertex_count);
PrimVtx(temp_outer[i], uv, col_trans);
PrimVtx(temp_outer[ni], uv, col_trans);
PrimVtx(points[ni], uv, col);
for (int i = 0; i < count; i++)
{
const int ni = (i+1) < points_count ? i+1 : 0;
const ImVec2& v0 = points[i];
const ImVec2& v1 = points[ni];
ImVec2 diff = v1 - v0;
float d = ImLengthSqr(diff);
if (d > 0)
diff *= 1.0f / sqrtf(d);
PrimVtx(temp_inner[ni], uv, col_trans);
PrimVtx(temp_inner[i], uv, col_trans);
PrimVtx(points[i], uv, col);
ImVec2 hn;
hn.x = diff.y * 0.5f;
hn.y = -diff.x * 0.5f;
PrimVtx(points[i], uv, col);
PrimVtx(points[ni], uv, col);
PrimVtx(temp_inner[ni], uv, col_trans);
PrimVtx(v0 - hn, uv, col);
PrimVtx(v0 + hn, uv, col);
PrimVtx(v1 + hn, uv, col);
PrimVtx(v0 - hn, uv, col);
PrimVtx(v1 + hn, uv, col);
PrimVtx(v1 - hn, uv, col);
}
/*
const float inv_length = 1.0f / sqrtf(ImLengthSqr(b - a));
const float aa_size = 1.0f;
const ImVec2 hn = (b - a) * (thickness * 0.5f * inv_length);// half normalized
const ImVec2 hp0 = ImVec2(+hn.y, -hn.x); // half perpendiculars + user offset
const ImVec2 hp1 = ImVec2(-hn.y, +hn.x);
*/
}
}
void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col)
{
const float aa_size = 1.0f;
// Temporary buffer
GTempPolyData.resize(points_count * 3);
ImVec2* temp_inner = &GTempPolyData[0];
ImVec2* temp_outer = &GTempPolyData[points_count];
ImVec2* temp_normals = &GTempPolyData[points_count * 2];
for (int i = 0, j = points_count-1; i < points_count; j=i++)
{
const ImVec2& v0 = points[j];
const ImVec2& v1 = points[i];
ImVec2 diff = v1 - v0;
float d = ImLengthSqr(diff);
if (d > 0)
diff *= 1.0f/sqrtf(d);
temp_normals[j].x = diff.y;
temp_normals[j].y = -diff.x;
}
for (int i = 0, j = points_count-1; i < points_count; j=i++)
{
const ImVec2& dl0 = temp_normals[j];
const ImVec2& dl1 = temp_normals[i];
ImVec2 dm = (dl0 + dl1) * 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*0.5f;
temp_outer[i] = points[i] + dm;
temp_inner[i] = points[i] - dm;
}
const ImU32 col_trans = col & 0x00ffffff;
const ImVec2 uv = GImGui->FontTexUvWhitePixel;
int vertex_count = (points_count-2)*3 + points_count*6;
PrimReserve(vertex_count);
// Fill
for (int i = 2; i < points_count; i++)
const bool aa_enabled = true;//!ImGui::GetIO().KeyCtrl;
if (aa_enabled)
{
PrimVtx(temp_inner[0], uv, col);
PrimVtx(temp_inner[i-1], uv, col);
PrimVtx(temp_inner[i], uv, col);
// Anti-aliased Fill
const float aa_size = 1.0f;
// Temporary buffer
GTempPolyData.resize(points_count * 3);
ImVec2* temp_inner = &GTempPolyData[0];
ImVec2* temp_outer = &GTempPolyData[points_count];
ImVec2* temp_normals = &GTempPolyData[points_count * 2];
for (int i = 0, j = points_count-1; i < points_count; j=i++)
{
const ImVec2& v0 = points[j];
const ImVec2& v1 = points[i];
ImVec2 diff = v1 - v0;
float d = ImLengthSqr(diff);
if (d > 0)
diff *= 1.0f/sqrtf(d);
temp_normals[j].x = diff.y;
temp_normals[j].y = -diff.x;
}
for (int i = 0, j = points_count-1; i < points_count; j=i++)
{
const ImVec2& dl0 = temp_normals[j];
const ImVec2& dl1 = temp_normals[i];
ImVec2 dm = (dl0 + dl1) * 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*0.5f;
temp_outer[i] = points[i] + dm;
temp_inner[i] = points[i] - dm;
}
const ImU32 col_trans = col & 0x00ffffff;
const int vertex_count = (points_count-2)*3 + points_count*6;
PrimReserve(vertex_count);
// Fill
for (int i = 2; i < points_count; i++)
{
PrimVtx(temp_inner[0], uv, col);
PrimVtx(temp_inner[i-1], uv, col);
PrimVtx(temp_inner[i], uv, col);
}
// AA fringe
for (int i = 0, j = points_count-1; i < points_count; j=i++)
{
PrimVtx(temp_inner[i], uv, col);
PrimVtx(temp_inner[j], uv, col);
PrimVtx(temp_outer[j], uv, col_trans);
PrimVtx(temp_outer[j], uv, col_trans);
PrimVtx(temp_outer[i], uv, col_trans);
PrimVtx(temp_inner[i], uv, col);
}
}
// AA fringe
for (int i = 0, j = points_count-1; i < points_count; j=i++)
else
{
PrimVtx(temp_inner[i], uv, col);
PrimVtx(temp_inner[j], uv, col);
PrimVtx(temp_outer[j], uv, col_trans);
PrimVtx(temp_outer[j], uv, col_trans);
PrimVtx(temp_outer[i], uv, col_trans);
PrimVtx(temp_inner[i], uv, col);
// Non Anti-aliased Fill
const int vertex_count = (points_count-2)*3;
PrimReserve(vertex_count);
for (int i = 2; i < points_count; i++)
{
PrimVtx(points[0], uv, col);
PrimVtx(points[i-1], uv, col);
PrimVtx(points[i], uv, col);
}
}
}
@ -7936,10 +7997,10 @@ void ImDrawList::Fill(ImU32 col)
ClearPath();
}
void ImDrawList::Stroke(ImU32 col, bool closed)
void ImDrawList::Stroke(ImU32 col, float thickness, bool closed)
{
// Remove duplicates
AddPolyline(&path[0], (int)path.size(), col, closed);
AddPolyline(&path[0], (int)path.size(), col, thickness, closed);
ClearPath();
}

View File

@ -914,7 +914,7 @@ struct ImDrawList
IMGUI_API void ArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 12);
IMGUI_API void Rect(const ImVec2& a, const ImVec2& b, float rounding = 0.0f, int rounding_corners = 0x0F);
IMGUI_API void Fill(ImU32 col);
IMGUI_API void Stroke(ImU32 col, bool closed = false);
IMGUI_API void Stroke(ImU32 col, float thickness, bool closed = false);
// Primitives
IMGUI_API void AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness = 1.0f);
@ -925,7 +925,7 @@ struct ImDrawList
IMGUI_API void AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12);
IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec2* cpu_clip_max = NULL);
IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv0, const ImVec2& uv1, ImU32 col = 0xFFFFFFFF);
IMGUI_API void AddPolyline(const ImVec2* points, const int num_points, ImU32 col, bool closed);
IMGUI_API void AddPolyline(const ImVec2* points, const int num_points, ImU32 col, float thickness, bool closed);
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, const int num_points, ImU32 col);
// Advanced