# How to Integrate Custom Math Types like glm::vec2 with Dear ImGui

> Seamlessly integrate glm::vec2 and custom math types with Dear ImGui. Learn how to adapt your vectors for powerful UI development without modifying imgui source code.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-30

---

**You can integrate glm::vec2 and other custom math types with Dear ImGui by providing conversion operators or wrapper functions that translate your vector types to ImGui's native ImVec2 struct, enabling seamless use without modifying the library source.**

The Dear ImGui library (`ocornut/imgui`) uses its own lightweight `ImVec2` structure for 2D coordinates, sizes, and layout calculations. When your application relies on GLM or another mathematics library, manually converting between vector types at every API call creates friction. Fortunately, the integration requires only zero-cost conversion patterns that live entirely in your codebase, leaving [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) and the core implementation untouched.

## Understanding ImVec2 and API Conventions

ImGui's public API in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) defines `ImVec2` as a plain-old-data struct containing two public `float` members:

```cpp
struct ImVec2 { float x, y; ImVec2() : x(0), y(0) {} ImVec2(float _x, float _y) : x(_x), _y(_y) {} };

```

API functions consume this type in two distinct patterns according to the source implementation in [imgui.h](https://github.com/ocornut/imgui/blob/master/imgui.h):

- **By value or const reference** for layout operations (e.g., `SetCursorPos(const ImVec2& pos)`, `SetNextWindowPos(const ImVec2& pos)`)
- **By pointer to float array** for multi-component widgets (e.g., `SliderFloat2(const char* label, float v[2], float v_min, float v_max)`)

Because `ImVec2` contains no private members, virtual functions, or complex constructors, converting from `glm::vec2` is a trivial copy of two floats that compilers optimize to a single instruction.

## Method 1: Conversion Operators and Helper Functions

The simplest integration adds explicit conversion utilities in a header you control.

### Implicit Conversion via Free Functions

Create a small bridging header (e.g., [`imgui_glm_bridge.h`](https://github.com/ocornut/imgui/blob/main/imgui_glm_bridge.h)) that includes both libraries and defines inline converters:

```cpp
#include <glm/vec2.hpp>
#include "imgui.h"

inline ImVec2 ToImVec(const glm::vec2& v) { 
    return ImVec2(v.x, v.y); 
}

inline glm::vec2 ToGlmVec(const ImVec2& v) { 
    return glm::vec2(v.x, v.y); 
}

```

With these helpers, you can pass GLM vectors directly to layout functions:

```cpp
glm::vec2 buttonPos(150.0f, 75.0f);
ImGui::SetCursorPos(ToImVec(buttonPos));
ImGui::Button("Click Me");

```

### Specializing for Your Math Library

If you can extend your math library's namespace without violating ODR, provide semantic conversion functions there for discoverability:

```cpp
namespace glm {
    inline ImVec2 to_imvec(const vec2& v) { 
        return ImVec2(v.x, v.y); 
    }
}

```

## Method 2: Pointer-Based Access for Multi-Component Widgets

Widgets editing multiple floats simultaneously, such as `SliderFloat2`, `InputFloat2`, and `DragFloat2`, expect a pointer to a contiguous array of floats rather than an `ImVec2`. GLM guarantees that `vec2` stores its components contiguously in memory, allowing direct pointer access.

Use `glm::value_ptr` from `<glm/gtc/type_ptr.hpp>` to obtain the address of the first component:

```cpp
#include <glm/vec2.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "imgui.h"

void EditVelocity(glm::vec2& velocity) {
    ImGui::SliderFloat2("Velocity", glm::value_ptr(velocity), -10.0f, 10.0f);
}

```

This pattern avoids any copying; ImGui writes directly into your `glm::vec2` memory.

## Method 3: Wrapper Functions for Type-Safe API

For large projects where you want ImGui calls to look native to your math types, write thin wrapper overloads that forward to the original API after conversion:

```cpp
// imgui_wrappers.h
#pragma once
#include <glm/vec2.hpp>
#include <glm/vec4.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "imgui.h"

inline void SetNextWindowPos(const glm::vec2& pos, ImGuiCond cond = 0, 
                             const glm::vec2& pivot = glm::vec2(0,0)) {
    ImGui::SetNextWindowPos(ImVec2(pos.x, pos.y), cond, ImVec2(pivot.x, pivot.y));
}

inline bool SliderFloat2(const char* label, glm::vec2& v, 
                         float v_min, float v_max, 
                         const char* format = "%.3f") {
    return ImGui::SliderFloat2(label, glm::value_ptr(v), v_min, v_max, format);
}

inline bool ColorEdit4(const char* label, glm::vec4& color) {
    return ImGui::ColorEdit4(label, glm::value_ptr(color));
}

```

These wrappers eliminate boilerplate at call sites while maintaining full compatibility with the underlying ImGui implementation defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) and [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h).

## Key Source Files and Implementation Details

Understanding where types are defined helps ensure your integration remains robust across updates:

- **[imgui.h](https://github.com/ocornut/imgui/blob/master/imgui.h)**: Contains the `ImVec2` and `ImVec4` struct definitions and the public API surface (e.g., `SetCursorPos`, `SetNextWindowSize`). Functions here accept `ImVec2` by value or const reference.
- **[imgui_internal.h](https://github.com/ocornut/imgui/blob/master/imgui_internal.h)**: Implements internal vector math utilities like `ImMin`, `ImMax`, and `ImFloor` that operate on `ImVec2`. While you typically do not call these directly, understanding their expectation of POD semantics confirms that conversion helpers should remain simple copies.
- **[misc/cpp/imgui_stdlib.h](https://github.com/ocornut/imgui/blob/master/misc/cpp/imgui_stdlib.h)**: Demonstrates the official pattern for extending ImGui with support for standard library types (specifically `std::string`). Use this as a reference for how to structure your own [`imgui_glm.h`](https://github.com/ocornut/imgui/blob/main/imgui_glm.h) extension header.
- **[backends/imgui_impl_opengl3.h](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.h)**: Shows how `ImVec2` values are passed to rendering backends, confirming that the struct layout must match exactly what the graphics API expects—reinforcing why keeping `ImVec2` as the boundary type is safest.

## Summary

- **ImVec2 is POD**: Defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) with public `float x, y` members, making it trivially convertible from any 2-float vector type.
- **Zero-cost conversion**: Converting `glm::vec2` to `ImVec2` copies two floats and adds no runtime overhead.
- **Two integration patterns**: Use conversion helpers (e.g., `ToImVec`) for layout functions accepting `ImVec2`, and `glm::value_ptr` for widget functions requiring raw `float*` arrays.
- **No source modifications**: Keep all bridging code in your own headers to preserve binary compatibility and simplify updates to the `ocornut/imgui` repository.
- **Extensible to other types**: The same patterns apply to `glm::vec3`, `glm::vec4`, and custom math structs with contiguous float storage.

## Frequently Asked Questions

### Can I replace ImVec2 with glm::vec2 inside ImGui's source code?

Modifying [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) to replace `ImVec2` with `glm::vec2` is strongly discouraged. Doing so breaks binary compatibility with the official library and complicates future updates. The supported approach is to provide conversion helpers in your own codebase while treating `ImVec2` strictly as a boundary type at the API surface.

### Do these conversion patterns add runtime overhead?

No. Converting `glm::vec2` to `ImVec2` involves copying two 32-bit floats, which modern compilers optimize into a single `mov` instruction or inline entirely. When using `glm::value_ptr` for functions like `SliderFloat2`, no copying occurs—ImGui writes directly into your vector's memory.

### How do I integrate glm::vec3 or glm::vec4 for color editing?

Apply the same principles used for `vec2`. For functions accepting `ImVec4` (such as `ColorEdit4` or `ColorPicker4`), create a helper: `inline ImVec4 ToImVec4(const glm::vec4& v) { return ImVec4(v.x, v.y, v.z, v.w); }`. Alternatively, pass `glm::value_ptr(vec4)` to functions expecting a `float[4]` array, such as `ColorEdit4(const char* label, float col[4])`.

### Where should I define my conversion utilities?

Place conversion helpers in a dedicated header file (e.g., [`imgui_glm.h`](https://github.com/ocornut/imgui/blob/main/imgui_glm.h) or [`math_bridge.h`](https://github.com/ocornut/imgui/blob/main/math_bridge.h)) that includes both [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) and your math library headers. This isolation prevents pollution of either library's namespace and makes it trivial to swap math libraries or update ImGui versions without merge conflicts.