Skip to content

Commit 38a0c17

Browse files
authored
feat: per-Index color/size support with ImPlot3DSpec (#182)
Feat: Per-Index Color/Size Support with ImPlot3DSpec
2 parents 42f27a2 + cbb0913 commit 38a0c17

5 files changed

Lines changed: 641 additions & 177 deletions

File tree

example/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ FetchContent_MakeAvailable(glfw)
2626
FetchContent_Declare(
2727
imgui
2828
GIT_REPOSITORY "https://github.com/ocornut/imgui"
29-
GIT_TAG "v1.92.4"
29+
GIT_TAG "v1.92.7"
3030
GIT_PROGRESS TRUE
3131
)
3232
FetchContent_MakeAvailable(imgui)

implot3d.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ Below is a change-log of API breaking changes only. If you are using one of the
4848
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all
4949
implot3d files. You can read releases logs https://github.com/brenocq/implot3d/releases for more details.
5050
51+
- 2026/04/04 (0.4) - PlotMesh signature changed: the ImPlot3DPoint* overload is deprecated and will be removed in v1.0.
52+
A new overload accepting separate coordinate arrays (vtx_xs, vtx_ys, vtx_zs) was added, matching
53+
the pattern of PlotLine/PlotScatter/PlotTriangle and supporting Spec.Offset and Spec.Stride.
54+
```cpp
55+
// Before
56+
ImPlot3D::PlotMesh("Mesh", vtx, idxs, vtx_count, idx_count);
57+
58+
// After
59+
ImPlot3D::PlotMesh("Mesh", vtx_xs, vtx_ys, vtx_zs, idxs, vtx_count, idx_count);
60+
```
5161
- 2026/02/03 (0.4) - ImPlotSpec was made the default and _only_ way of styling plot items. The SetNextXXXStyle functions have been removed.
5262
- SetNextLineStyle has been removed, styling should be set via ImPlot3DSpec.
5363
```cpp
@@ -631,7 +641,7 @@ float ComputeMaxTickLabelExtent(const ImPlot3DAxis& axis);
631641

632642
// Spacing constants for axis tick labels and axis labels
633643
static const float AXIS_TICK_INNER_PAD = 5.0f; // gap between axis edge and inner edge of tick labels
634-
static const float AXIS_LABEL_PAD = 10.0f; // gap between tick label outer edge and axis label center
644+
static const float AXIS_LABEL_PAD = 10.0f; // gap between tick label outer edge and axis label center
635645
static const float AXIS_RECT_MIN_WIDTH = 40.0f; // minimum hover rect width when labels are absent
636646

637647
// Computes the total outward width of the hover rect for an axis
@@ -2898,7 +2908,7 @@ struct ImPlot3DStyleVarInfo {
28982908
static const ImPlot3DStyleVarInfo GPlot3DStyleVarInfo[] = {
28992909
// Item style
29002910
{ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlot3DStyle, LineWeight)}, // ImPlot3DStyleVar_LineWeight
2901-
{ImGuiDataType_S32, 1, (ImU32)offsetof(ImPlot3DStyle, Marker)}, // ImPlot3DStyleVar_Marker
2911+
{ImGuiDataType_S32, 1, (ImU32)offsetof(ImPlot3DStyle, Marker)}, // ImPlot3DStyleVar_Marker
29022912
{ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlot3DStyle, MarkerSize)}, // ImPlot3DStyleVar_MarkerSize
29032913
{ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlot3DStyle, FillAlpha)}, // ImPlot3DStyleVar_FillAlpha
29042914

implot3d.h

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,22 @@ typedef ImTextureID ImTextureRef;
103103

104104
// Plotting properties. These provide syntactic sugar for creating ImPlot3DSpec from (ImPlot3DProp,value) pairs
105105
enum ImPlot3DProp_ {
106-
ImPlot3DProp_LineColor, // Line color; IMPLOT3D_AUTO_COL will use next Colormap color
107-
ImPlot3DProp_LineWeight, // Line weight in pixels
108-
ImPlot3DProp_FillColor, // Fill color (applies to shaded regions); IMPLOT3D_AUTO_COL will use next Colormap color
109-
ImPlot3DProp_FillAlpha, // Alpha multiplier (applies to FillColor and MarkerFillColor)
110-
ImPlot3DProp_Marker, // Marker type
111-
ImPlot3DProp_MarkerSize, // Size of markers (radius) *in pixels*
112-
ImPlot3DProp_MarkerLineColor, // Marker outline color; IMPLOT3D_AUTO_COL will use next LineColor
113-
ImPlot3DProp_MarkerFillColor, // Marker fill color; IMPLOT3D_AUTO_COL will use LineColor
114-
ImPlot3DProp_Offset, // Data index offset
115-
ImPlot3DProp_Stride, // Data stride in bytes; IMPLOT3D_AUTO will result in sizeof(T) where T is the type passed to PlotX
116-
ImPlot3DProp_Flags // Optional item flags; can be composed from common ImPlot3DItemFlags and/or specialized ImPlot3DXFlags
106+
ImPlot3DProp_LineColor, // Line color; IMPLOT3D_AUTO_COL will use next Colormap color
107+
ImPlot3DProp_LineColors, // Array of line colors (ImU32*); if nullptr, use LineColor for all
108+
ImPlot3DProp_LineWeight, // Line weight in pixels
109+
ImPlot3DProp_FillColor, // Fill color (applies to shaded regions); IMPLOT3D_AUTO_COL will use next Colormap color
110+
ImPlot3DProp_FillColors, // Array of fill colors (ImU32*); if nullptr, use FillColor for all
111+
ImPlot3DProp_FillAlpha, // Alpha multiplier (applies to FillColor, FillColors, MarkerFillColor, and MarkerFillColors)
112+
ImPlot3DProp_Marker, // Marker type
113+
ImPlot3DProp_MarkerSize, // Size of markers (radius) *in pixels*
114+
ImPlot3DProp_MarkerSizes, // Array of marker sizes (float*); if nullptr, use MarkerSize for all
115+
ImPlot3DProp_MarkerLineColor, // Marker outline color; IMPLOT3D_AUTO_COL will use next LineColor
116+
ImPlot3DProp_MarkerLineColors, // Array of marker outline colors (ImU32*); if nullptr, use MarkerLineColor for all
117+
ImPlot3DProp_MarkerFillColor, // Marker fill color; IMPLOT3D_AUTO_COL will use LineColor
118+
ImPlot3DProp_MarkerFillColors, // Array of marker fill colors (ImU32*); if nullptr, use MarkerFillColor for all
119+
ImPlot3DProp_Offset, // Data index offset
120+
ImPlot3DProp_Stride, // Data stride in bytes; IMPLOT3D_AUTO will result in sizeof(T) where T is the type passed to PlotX
121+
ImPlot3DProp_Flags // Optional item flags; can be composed from common ImPlot3DItemFlags and/or specialized ImPlot3DXFlags
117122
};
118123

119124
// Flags for ImPlot3D::BeginPlot()
@@ -378,13 +383,18 @@ enum ImPlot3DColormap_ {
378383
// });
379384
struct ImPlot3DSpec {
380385
ImVec4 LineColor = IMPLOT3D_AUTO_COL; // Line color; IMPLOT3D_AUTO_COL will use next Colormap color
386+
ImU32* LineColors = nullptr; // Per-index line colors; if nullptr, use LineColor for all
381387
float LineWeight = 1.0f; // Line weight in pixels
382388
ImVec4 FillColor = IMPLOT3D_AUTO_COL; // Fill color (applies to shaded regions); IMPLOT3D_AUTO_COL will use next Colormap color
383-
float FillAlpha = IMPLOT3D_AUTO; // Alpha multiplier (applies to FillColor and MarkerFillColor)
389+
ImU32* FillColors = nullptr; // Per-index fill colors; if nullptr, use FillColor for all
390+
float FillAlpha = IMPLOT3D_AUTO; // Alpha multiplier (applies to FillColor, FillColors, MarkerFillColor, and MarkerFillColors)
384391
ImPlot3DMarker Marker = ImPlot3DMarker_Auto; // Marker type
385392
float MarkerSize = IMPLOT3D_AUTO; // Size of markers (radius) *in pixels*
393+
float* MarkerSizes = nullptr; // Per-index marker sizes; if nullptr, use MarkerSize for all
386394
ImVec4 MarkerLineColor = IMPLOT3D_AUTO_COL; // Marker outline color; IMPLOT3D_AUTO_COL will use LineColor
395+
ImU32* MarkerLineColors = nullptr; // Per-index marker outline colors; if nullptr, use MarkerLineColor for all
387396
ImVec4 MarkerFillColor = IMPLOT3D_AUTO_COL; // Marker fill color; IMPLOT3D_AUTO_COL will use LineColor
397+
ImU32* MarkerFillColors = nullptr; // Per-index marker fill colors; if nullptr, use MarkerFillColor for all
388398
int Offset = 0; // Data index offset
389399
int Stride = IMPLOT3D_AUTO; // Data stride in bytes; IMPLOT3D_AUTO will result in sizeof(T) where T is the type passed to PlotX
390400
ImPlot3DItemFlags Flags =
@@ -426,6 +436,27 @@ struct ImPlot3DSpec {
426436
IM_ASSERT(0 && "User provided an ImPlot3DProp which cannot be set from scalar value!");
427437
}
428438

439+
// Set a property from an ImU32* array (per-index colors).
440+
void SetProp(ImPlot3DProp prop, ImU32* v) {
441+
switch (prop) {
442+
case ImPlot3DProp_LineColors: LineColors = v; return;
443+
case ImPlot3DProp_FillColors: FillColors = v; return;
444+
case ImPlot3DProp_MarkerLineColors: MarkerLineColors = v; return;
445+
case ImPlot3DProp_MarkerFillColors: MarkerFillColors = v; return;
446+
default: break;
447+
}
448+
IM_ASSERT(0 && "User provided an ImPlot3DProp which cannot be set from ImU32* value!");
449+
}
450+
451+
// Set a property from a float* array (per-index sizes).
452+
void SetProp(ImPlot3DProp prop, float* v) {
453+
switch (prop) {
454+
case ImPlot3DProp_MarkerSizes: MarkerSizes = v; return;
455+
default: break;
456+
}
457+
IM_ASSERT(0 && "User provided an ImPlot3DProp which cannot be set from float* value!");
458+
}
459+
429460
// Set a property from an ImVec4 value.
430461
void SetProp(ImPlot3DProp prop, const ImVec4& v) {
431462
switch (prop) {
@@ -620,9 +651,18 @@ IMPLOT3D_TMP void PlotQuad(const char* label_id, const T* xs, const T* ys, const
620651
IMPLOT3D_TMP void PlotSurface(const char* label_id, const T* xs, const T* ys, const T* zs, int x_count, int y_count, double scale_min = 0.0,
621652
double scale_max = 0.0, const ImPlot3DSpec& spec = ImPlot3DSpec());
622653

623-
// Plots a 3D mesh given vertex positions and indices. Triangles are defined by the index buffer (every 3 indices form a triangle)
624-
IMPLOT3D_API void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int* idx, int vtx_count, int idx_count,
625-
const ImPlot3DSpec& spec = ImPlot3DSpec());
654+
// Plots a 3D mesh given vertex positions as separate coordinate arrays and an index buffer.
655+
// Triangles are defined by the index buffer (every 3 indices form a triangle).
656+
// Spec.Offset and Spec.Stride apply to the vertex coordinate arrays only, not to the index buffer.
657+
// Color array semantics:
658+
// - FillColors / LineColors: idx_count entries, indexed by position in the index buffer.
659+
// Each triangle has 3 consecutive color entries (one per corner).
660+
// Setting all 3 to the same value gives flat per-triangle shading.
661+
// Setting different values enables Gouraud shading (GPU-interpolated).
662+
// To shade by vertex, map: FillColors[i] = vtx_colors[idxs[i]].
663+
// - MarkerFillColors / MarkerLineColors: vtx_count entries, one per unique vertex.
664+
IMPLOT3D_TMP void PlotMesh(const char* label_id, const T* vtx_xs, const T* vtx_ys, const T* vtx_zs, const unsigned int* idxs, int vtx_count,
665+
int idx_count, const ImPlot3DSpec& spec = ImPlot3DSpec());
626666

627667
// Plots a rectangular image in 3D defined by its center and two direction vectors (axes).
628668
// #center is the center of the rectangle in plot coordinates.
@@ -1011,8 +1051,7 @@ struct ImPlot3DStyle {
10111051
// Constructor
10121052
IMPLOT3D_API ImPlot3DStyle();
10131053
ImPlot3DStyle(const ImPlot3DStyle& other) = default;
1014-
ImPlot3DStyle& operator=(const ImPlot3DStyle& other) =
1015-
default;
1054+
ImPlot3DStyle& operator=(const ImPlot3DStyle& other) = default;
10161055
};
10171056

10181057
//-----------------------------------------------------------------------------
@@ -1069,16 +1108,26 @@ extern unsigned int duck_idx[DUCK_IDX_COUNT]; // Duck indices
10691108
namespace ImPlot3D {
10701109

10711110
// OBSOLETED in v0.4 (from February 2026)
1072-
// IMPLOT_API void SetNextLineStyle(const ImVec4& col = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO); // OBSOLETED IN v0.4 // Set ImPlotSpec.LineColor/LineWeight or construct ImPlotSpec with { ImPlotSpec_LineColor, color, ImPlotSpec_LineWeight, weight }.
1111+
// IMPLOT_API void SetNextLineStyle(const ImVec4& col = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO); // OBSOLETED IN v0.4 // Set
1112+
// ImPlotSpec.LineColor/LineWeight or construct ImPlotSpec with { ImPlotSpec_LineColor, color, ImPlotSpec_LineWeight, weight }.
10731113

1074-
// IMPLOT_API void SetNextFillStyle(const ImVec4& col = IMPLOT_AUTO_COL, float alpha_mod = IMPLOT_AUTO);// OBSOLETED IN v0.4 // Set ImPlotSpec.FillColor/FillAlpha or construct ImPlotSpec with { ImPlotSpec_FillColor, color, ImPlotSpec_FillAlpha, alpha }.
1114+
// IMPLOT_API void SetNextFillStyle(const ImVec4& col = IMPLOT_AUTO_COL, float alpha_mod = IMPLOT_AUTO);// OBSOLETED IN v0.4 // Set
1115+
// ImPlotSpec.FillColor/FillAlpha or construct ImPlotSpec with { ImPlotSpec_FillColor, color, ImPlotSpec_FillAlpha, alpha }.
10751116

1076-
// IMPLOT_API void SetNextMarkerStyle(ImPlotMarker marker = IMPLOT_AUTO, float size = IMPLOT_AUTO, const ImVec4& fill = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO, const ImVec4& outline = IMPLOT_AUTO_COL); // OBSOLETED IN v0.4 // Set ImPlotSpec.Marker/MarkerSize/MarkerFillColor/LineWeight/MarkerLineColor or construct ImPlotSpec with { ImPlotSpec_Marker, marker, ImPlotSpec_MarkerSize, size, ImPlotSpec_MarkerFillColor, fill_color, ImPlotSpec_LineWeight, weight, ImPlotSpec_MarkerLineColor, outline }.
1117+
// IMPLOT_API void SetNextMarkerStyle(ImPlotMarker marker = IMPLOT_AUTO, float size = IMPLOT_AUTO, const ImVec4& fill = IMPLOT_AUTO_COL, float weight
1118+
// = IMPLOT_AUTO, const ImVec4& outline = IMPLOT_AUTO_COL); // OBSOLETED IN v0.4 // Set
1119+
// ImPlotSpec.Marker/MarkerSize/MarkerFillColor/LineWeight/MarkerLineColor or construct ImPlotSpec with { ImPlotSpec_Marker, marker,
1120+
// ImPlotSpec_MarkerSize, size, ImPlotSpec_MarkerFillColor, fill_color, ImPlotSpec_LineWeight, weight, ImPlotSpec_MarkerLineColor, outline }.
10771121

10781122
// OBSOLETED in v0.3 -> PLANNED REMOVAL in v1.0
10791123
IMPLOT3D_DEPRECATED(IMPLOT3D_API ImVec2 GetPlotPos()); // Renamed to GetPlotRectPos()
10801124
IMPLOT3D_DEPRECATED(IMPLOT3D_API ImVec2 GetPlotSize()); // Renamed to GetPlotRectSize()
10811125

1126+
// OBSOLETED in v0.4 -> PLANNED REMOVAL in v1.0
1127+
// Use PlotMesh(label_id, vtx_xs, vtx_ys, vtx_zs, idx, vtx_count, idx_count, spec) instead.
1128+
IMPLOT3D_DEPRECATED(IMPLOT3D_API void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int* idxs, int vtx_count, int idx_count,
1129+
const ImPlot3DSpec& spec = ImPlot3DSpec()));
1130+
10821131
} // namespace ImPlot3D
10831132

10841133
#endif // #ifndef IMPLOT3D_DISABLE_OBSOLETE_FUNCTIONS

0 commit comments

Comments
 (0)