New MousePointer Brownian

This commit is contained in:
brunoherbelin
2025-11-18 17:13:27 +01:00
parent 97a58c2988
commit cc6189e162
3 changed files with 64 additions and 1 deletions

Binary file not shown.

View File

@@ -17,6 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
**/
#include <glm/geometric.hpp>
#include <glm/gtc/random.hpp> // for diskRand
#include "imgui.h"
@@ -37,6 +38,7 @@ std::vector< std::tuple<int, int, std::string, std::string> > Pointer::Modes = {
{ ICON_POINTER_LINEAR, "Line", "Speed" },
{ ICON_POINTER_SPRING, "Spring", "Mass" },
{ ICON_POINTER_WIGGLY, "Wiggly", "Radius" },
{ ICON_POINTER_BROWNIAN, "Brownian", "Radius" },
{ ICON_POINTER_METRONOME, "Metronome", "Jump" }
};
@@ -138,6 +140,49 @@ void PointerWiggly::draw()
ImGui::GetBackgroundDrawList()->AddCircle(IMVEC_IO(current_), max * 0.5f, color, 0, 2.f + 4.f * strength_);
}
void PointerBrownian::update(const glm::vec2 &pos, float)
{
current_ = pos;
radius_ = (POINTER_WIGGLY_MAX_RADIUS - POINTER_WIGGLY_MIN_RADIUS) * strength_;
radius_ += POINTER_WIGGLY_MIN_RADIUS;
// Brownian motion: add small random displacement in 2D
// Generate random step using gaussian distribution for each axis
glm::vec2 random_step = glm::gaussRand(glm::vec2(0.0f), glm::vec2(1.f) );
// Scale by radius and apply damping to keep motion bounded
float factor = 0.3f;
if (TabletInput::instance().hasPressure() && TabletInput::instance().isPressed()) {
factor *= TabletInput::instance().getPressure();
}
float damping = 0.92f;
brownian_offset_ = brownian_offset_ * damping + random_step * radius_ * factor;
// Clamp offset to stay within maximum radius
float offset_length = glm::length(brownian_offset_);
if (offset_length > radius_) {
brownian_offset_ = brownian_offset_ * (radius_ / offset_length);
}
glm::vec2 p = pos + brownian_offset_;
// smooth a little and apply
const float emaexp = 2.0 / float( POINTER_WIGGLY_SMOOTHING + 1);
target_ = emaexp * p + (1.f - emaexp) * target_;
}
void PointerBrownian::draw()
{
const ImU32 color = ImGui::GetColorU32(ImGuiCol_HeaderActive);
ImGui::GetBackgroundDrawList()->AddLine(IMVEC_IO(current_), IMVEC_IO(target_), color, 5.f);
const float max = POINTER_WIGGLY_MIN_RADIUS + (POINTER_WIGGLY_MAX_RADIUS - POINTER_WIGGLY_MIN_RADIUS) * strength_;
if (TabletInput::instance().hasPressure() && TabletInput::instance().isPressed())
ImGui::GetBackgroundDrawList()->AddCircle(IMVEC_IO(current_), radius_ * 0.8f, color, 0);
ImGui::GetBackgroundDrawList()->AddCircle(IMVEC_IO(current_), max * 0.8f, color, 0, 2.f + 4.f * strength_);
}
#define POINTER_METRONOME_RADIUS 36.f
void PointerMetronome::initiate(const glm::vec2 &pos)
@@ -256,6 +301,7 @@ MousePointer::MousePointer() : mode_(Pointer::POINTER_DEFAULT)
pointer_[Pointer::POINTER_LINEAR] = new PointerLinear;
pointer_[Pointer::POINTER_SPRING] = new PointerSpring;
pointer_[Pointer::POINTER_WIGGLY] = new PointerWiggly;
pointer_[Pointer::POINTER_BROWNIAN] = new PointerBrownian;
pointer_[Pointer::POINTER_METRONOME] = new PointerMetronome;
}
@@ -266,5 +312,6 @@ MousePointer::~MousePointer()
delete pointer_[Pointer::POINTER_LINEAR];
delete pointer_[Pointer::POINTER_SPRING];
delete pointer_[Pointer::POINTER_WIGGLY];
delete pointer_[Pointer::POINTER_BROWNIAN];
delete pointer_[Pointer::POINTER_METRONOME];
}

View File

@@ -12,6 +12,7 @@
#define ICON_POINTER_LINEAR 14, 9
#define ICON_POINTER_GRID 15, 9
#define ICON_POINTER_WIGGLY 16, 9
#define ICON_POINTER_BROWNIAN 11, 9
#define ICON_POINTER_METRONOME 6, 13
///
@@ -33,6 +34,7 @@ public:
POINTER_LINEAR,
POINTER_SPRING,
POINTER_WIGGLY,
POINTER_BROWNIAN,
POINTER_METRONOME,
POINTER_INVALID
} Mode;
@@ -104,7 +106,21 @@ class PointerWiggly : public Pointer
{
float radius_;
public:
PointerWiggly() {}
PointerWiggly() : radius_(0.0f) {}
void update(const glm::vec2 &pos, float) override;
void draw() override;
};
///
/// \brief The PointerBrownian moves with a Brownian movement
/// Strength modulates the radius of the movement
///
class PointerBrownian : public Pointer
{
float radius_;
glm::vec2 brownian_offset_;
public:
PointerBrownian() : brownian_offset_(0.0f, 0.0f) {}
void update(const glm::vec2 &pos, float) override;
void draw() override;
};