Reputation: 61
I try to make a 3D game by using SDL2 and OpenGL 4.6 core mode, but I found a problem that makes me confused, and I don't know how to fix it, the code is following below:
// SDL2 initialize
// Create a SDL2 window
// Create a OpenGL 4.6 core context
// GLAD initialize
// ImGui initialize
// SDL Settings
SDL_SetHintWithPriority(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1", SDL_HINT_OVERRIDE);
// main loop
bool done = false;
bool relative = false;
while (!done) {
SDL_Event event;
while(SDL_PollEvent(&event)) {
if (event.type == SDL_MOUSEBUTTONDOWN) {
if (event.button.button == SDL_BUTTON_LEFT) {
relative = true;
}
}
if (event.type == SDL_MOUSEBUTTONUP) {
if (event.button.button == SDL_BUTTON_LEFT) {
relative = false;
}
}
if (event.type == SDL_MOUSEMOTION) {
std::cout << "Mouse Motion Triggered: (" + std::to_string(event.motion.xrel) + " ," + std::to_string(event.motion.yrel) + ")" << std::endl;
}
}
if (relative) {
SDL_SetRelativeMouseMode(SDL_TRUE);
} else {
SDL_SetRelativeMouseMode(SDL_FALSE);
}
// Render ImGui
SDL_GL_SwapWindow(window);
}
As you can see, when I hold the mouse left button down all the time, and then move the mouse from the left-top of the screen to the right-down of the screen, I expect the relative mouse motion return will be like this.
Mouse Motion Triggered: (11 ,6)
Mouse Motion Triggered: (13 ,8)
Mouse Motion Triggered: (14 ,8)
Mouse Motion Triggered: (14 ,8)
Mouse Motion Triggered: (16 ,9)
Mouse Motion Triggered: (15 ,7)
Mouse Motion Triggered: (11 ,6)
Mouse Motion Triggered: (10 ,6)
The relative coordinates x and y value both should be a positive number, but it's not, the actual result will be like this:
Mouse Motion Triggered: (1 ,1)
Mouse Motion Triggered: (2 ,2)
Mouse Motion Triggered: (-6 ,-4)
Mouse Motion Triggered: (3 ,3)
Mouse Motion Triggered: (1 ,1)
Mouse Motion Triggered: (-2 ,-3)
Mouse Motion Triggered: (2 ,2)
Mouse Motion Triggered: (1 ,1)
Mouse Motion Triggered: (-4 ,-4)
Mouse Motion Triggered: (3 ,3)
Mouse Motion Triggered: (-3 ,-3)
Mouse Motion Triggered: (1 ,1)
Mouse Motion Triggered: (-2 ,-2)
Mouse Motion Triggered: (1 ,2)
Mouse Motion Triggered: (-2 ,-2)
This causes my mouse position forces to lock in the middle of the screen, and then I try to fix this problem, I rewrite the code for the event handler like this:
if (event.type == SDL_MOUSEBUTTONDOWN) {
if (event.button.button == SDL_BUTTON_LEFT) {
relative = true;
std::cout << "relative: " << relative << std::endl;
}
if (event.button.button == SDL_BUTTON_RIGHT) {
relative = false;
std::cout << "relative: " << relative << std::endl;
}
}
if (event.type == SDL_MOUSEBUTTONUP) {
// Now this event is empty.
}
I realize if I just press down the mouse left button once, and move the mouse in the same direction, the whole functional works normally, but what if I hold the mouse left button all the time and move the mouse in the same direction, the relative mouse return value event.motion.xrel
and event.motion.yrel
will be very strange, these will give an oppositive direction that to force to make my mouse position back to the center of the screen, and I don't have any ideas why this happened.
What is the problem?
Environment details
Upvotes: 0
Views: 1294
Reputation: 11
I know this is an old question, but I ran into this even without using ImGui, and I wanted to post the answer for anyone in the future that has the same problem.
If you accidentally call SDL_SetRelativeMouseMode(SDL_TRUE);
before your SDL_Init
call, you will get the behaviour OP described, where mouse motion events are followed by mouse motion events going the opposite direction, causing jittering if you are trying to make an FPS-game-like control scheme. There is no error messaging from SDL unfortunately, this is just the behaviour that you will end up with. The solution is just to do SDL_SetRelativeMouseMode(SDL_TRUE);
after the init.
My project had a rogue SDL_SetRelativeMouseMode(SDL_TRUE);
hiding in the constructor of a class that was instantiated before my SDL_Init
, which made tracking it down very hard. If you have this problem, make sure you search your project for all references to that function!
Upvotes: 1
Reputation: 61
I found the main reason that causes the xrel
and yrel
values to become so wried, that is ImGui_ImplSDL2_NewFrame(window)
. When I comment out this code, the relative mouse report normally, but what if I add this line into the main loop, the relative mouse will report weird coordinate that force my mouse back to the center of the screen, I doubt maybe is the ImGui try to control the mouse event and it has a control conflict with something that I exactly don't know.
I saw the source code imgui_impl_sdl.cpp
, but I still don't know why this will happen, the solution for this problem is I make a toggle key which is tapping the TAB key to control the mouse for camera or GUI.
Here is my latest code:
// SDL2 initialize
// Create a SDL2 window
// Create a OpenGL 4.6 core context
// GLAD initialize
// ImGui initialize
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGui_ImplSDL2_InitForOpenGL(window, context);
ImGui_ImplOpenGL3_Init("#version 330");
ImGui::StyleColorsDark();
ImGuiIO &io = ImGui::GetIO();
// SDL Settings
SDL_SetHintWithPriority(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1", SDL_HINT_OVERRIDE);
SDL_SetRelativeMouseMode(SDL_TRUE);
// main loop
bool done = false;
while (!done) {
SDL_Event event;
while(SDL_PollEvent(&event)) {
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_MOUSEMOTION) {
std::cout << "Mouse Motion Triggered: (" + std::to_string(event.motion.xrel) + " ," + std::to_string(event.motion.yrel) + ")" << std::endl;
}
}
// Render ImGui
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame(window); // <-- this is the main reason
//ImGui::NewFrame();
//ImGui::Render();
//ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
SDL_GL_SwapWindow(window);
}
// Delete ImGui and SDL Context, Window and SDL_QUIT()
ImGui version: 1.83
Upvotes: 1