Choppy FPS camera on Linux

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
RungAaz
Posts: 11
Joined: Sat Jun 19, 2010 9:18 am

Choppy FPS camera on Linux

Post by RungAaz »

Hey guys,

after playing around with the Irrlicht examples I noticed that on my Linux machine the FPS camera makes very choppy movements when i use the mouse to "look around".
I tested the example (see below) on my Linux machine and on my Windows Notebook. On my Windows Notebook the camera movement is perfectly smooth. But that's not all yet: If I run the example on Linux with valgrind (which I use for mem-checking) the camera movements are also perfectly smooth.
This brings me to the assumption, that the problem might be a frames-rate issue, since valgrind usually slows down the performance.

I found this thread on the forums, but it seems a bit outdated, since there is no CCameraFPSSceneNode class but a CSceneNodeAnimatorCameraFPS class that handels the movement.

Have you ever expierenced something similar? Or do you know what's the problem here?
Thanks in advance!

Regards


--------------------------------------------------------------------------------------------------
PS: Here is the code example "src/main.cpp" and also the Makefile "makefile"
To run the example you will also need the quake3 map package file "map-20kdm2.pk3" from the Irrlicht examples.
The structure for this example must be:
  • Makefile
  • src/main.cpp
  • media/map-20kdm2.pk3
Make targets:
  • make: Build example
  • make run: Run example (also builds the example, if necessary)
  • make mcf: Run example with valgrind (only works on Linux)
src/main.cpp:

Code: Select all

 
/*******************************************************************************
 * Irrlicht FPS camera example
 ******************************************************************************/
 
#include <iostream>
#include <exception>
 
#include <irrlicht/irrlicht.h>
 
using namespace irr;
 
 
/* -------------------------------------------------------------------------- */
/* custom message exception */
 
class ECustomMessageException : public std::exception
{
public:
    ECustomMessageException(const std::string& msg) throw() :
        message(msg) {};
    virtual ~ECustomMessageException() throw() {};
 
    virtual const char* what() const throw()
    {
        return message.c_str();
    }
 
protected:
    std::string message;
};
 
 
/* -------------------------------------------------------------------------- */
/* global variables - to make the example quick and dirty */
IrrlichtDevice* device         = NULL;
video::IVideoDriver* driver    = NULL;
scene::ISceneManager* scenemgr = NULL;
 
 
/* -------------------------------------------------------------------------- */
 
 
void loadMap(const io::path& map_package_filename, const io::path& map_name, const core::vector3df& position)
{
    scene::IAnimatedMesh* map_mesh  = NULL;
    scene::IMeshSceneNode* map_node = NULL;
 
    device->getFileSystem()->addFileArchive(map_package_filename);
    map_mesh = scenemgr->getMesh(map_name);
    if (map_mesh)
    {
        map_node = scenemgr->addOctreeSceneNode(map_mesh->getMesh(0), 0, -1, 1024);
        if (map_node)
            map_node->setPosition(position);
        else
            throw ECustomMessageException(
                "Failed to add map mesh as scene node to the scene manager");
    }
    else
        throw ECustomMessageException("Unable to load map file");
}
 
void setupCamera()
{
        device->getCursorControl()->setVisible(false);
        scenemgr->addCameraSceneNodeFPS(NULL, 100.0f, 0.3f);
}
 
int main(int argc, char* argv[])
{
    /* define initial return value */
    int exit_code = 0;
 
    try
    {
        /* setup irrlicht and global variables */
        device   = createDevice(video::EDT_OPENGL, core::dimension2du(800, 600), 16, false, false, false);
        driver   = device->getVideoDriver();
        scenemgr = device->getSceneManager();
 
        /* setup fps camera */
        setupCamera();
 
        /* load quake3 map */
        loadMap("media/map-20kdm2.pk3", "20kdm2.bsp", core::vector3df(-1350,-130,-1400));
 
 
        /* main game loop */
        while(device->run())
        {
            driver->beginScene(true, true, video::SColor(128, 128, 128, 140));
            scenemgr->drawAll();
            driver->endScene();
        }
 
        /* cleanup */
        device->drop();
 
        exit_code = 0;
    }
    catch (const std::exception& e)
    {
        exit_code = -1;
        std::cerr << "FATAL ERROR: [" << e.what() << "]" << std::endl;
    }
 
    return exit_code;
}
 
Makefile:

Code: Select all

 
################################################################################
# irrlicht_test -- Test for the irrlicht library
################################################################################
 
TARGET           := irrlicht_test
ifeq ($(OS), Windows_NT)
TARGET           := $(TARGET).exe
endif
 
SRC_DIR          := src
INC_DIR          := src
OBJ_DIR          := obj
SOURCES          := main.cpp
OBJECTS          := $(SOURCES:%.cpp=%.o)
OBJ              := $(OBJECTS:%=$(OBJ_DIR)/%)
 
CXXFLAGS_COMMON  := -Wall -pedantic-errors -std=c++11 -I$(INC_DIR)
CXXFLAGS         := -g $(CXXFLAGS_COMMON) -D DEBUG
CXXFLAGS_RELEASE := $(CXXFLAGS_COMMON)
LDFLAGS          := -lIrrlicht
 
MKDIR            := mkdir -p
GDB              := gdb
VALGRIND         := valgrind
VALGRIND_OPTIONS := --tool=memcheck
 
ifeq ($(OS), Windows_NT)
CXX              := x86_64-w64-mingw32-g++
endif
 
 
# ------------------------------------------------------------------------------
# BUILD (main target)
 
# default target
default: debug
 
debug: build
 
release: CXXFLAGS := $(CXXFLAGS_RELEASE)
release: build
 
build: object_dir $(TARGET)
 
$(TARGET): $(OBJ)
    $(CXX) -o $@ $^ $(LDFLAGS)
 
# build object files
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
    $(CXX) $(CXXFLAGS) -o $@ -c $<
 
# create object file directory
object_dir: $(OBJ_DIR)/
$(OBJ_DIR)/:
    $(MKDIR) $@
 
.PHONY: default debug release build object_dir
 
 
# ------------------------------------------------------------------------------
# EXECUTION
 
# execution of main target
run: build
    @./$(TARGET)
 
rund:     rundebug
rundebug: build
    $(GDB) ./$(TARGET)
 
.PHONY: run rund rundebug
 
 
# ------------------------------------------------------------------------------
# MEMORY-CHECK
 
# memory-check for main target
mc:       memcheck
memcheck: build
    $(VALGRIND) $(VALGRIND_OPTIONS) ./$(TARGET)
 
mcf:           memcheck-full
memcheck-full: VALGRIND_OPTIONS := $(VALGRIND_OPTIONS) --leak-check=full
memcheck-full: build
    $(VALGRIND) $(VALGRIND_OPTIONS) ./$(TARGET)
 
.PHONY: mc memcheck mcf memcheck-full
 
 
# ------------------------------------------------------------------------------
# CLEANUP
 
# cleanup main target
clean:
    $(RM) $(TARGET) $(OBJ)
 
rebuild: clean default
 
.PHONY: clean rebuild
 
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Choppy FPS camera on Linux

Post by hendu »

IIRC it was X sometimes taking up a couple ms to relay the cursor position. Try to run vsynced, which limits fps to 60?
RungAaz
Posts: 11
Joined: Sat Jun 19, 2010 9:18 am

Re: Choppy FPS camera on Linux

Post by RungAaz »

Running the example vsynced unfortunately doesn't fix the problem.
But the hint with the cursor position reset is interesting ... I read through the code of CSceneNodeAnimatorCameraFPS a bit and I noticed that in CSceneNodeAnimatorCameraFPS::animate() the cursor position will be reset to center

Code: Select all

core::dimension2df(0.5f, 0.5f)
as soon as the cursor position exceeds the window's borders.
Maybe I play around with CSceneNodeAnimatorCameraFPS a bit and try to find out if it's the cursor positioning.

Thanks!
RungAaz
Posts: 11
Joined: Sat Jun 19, 2010 9:18 am

Re: Choppy FPS camera on Linux

Post by RungAaz »

After a lot of testing and reading through Irrlicht's source i can say it's most likely the

Code: Select all

CursorControl->setPosition(0.5f, 0.5f);
call in CSceneNodeAnimatorCameraFPS.cpp, Line 171.
If I run the example under Wayland ("Gnome under Wayland"), it seems like the cursor position isn't reset, because the camera movement is going crazy (camera is rotating wildly). But after all, it's going crazy "smoothly" :wink:
I also copied the class CSceneNodeAnimatorCameraFPS from Irrlicht's source directory, slightly modified it to be able to compile in my example and used the code from CSceneManager::addCameraSceneNodeFPS() to attach the custom animator to a regular camera scene node. After that I deleted the call

Code: Select all

CursorControl->setPosition(0.5f, 0.5f);
mentioned above, compiled an ran it. The result was kind of the same like the experiment with Wayland.

As far as I know, there is no way around this. Maybe i could recompile Irrlicht to use CIrrDeviceSDL instead of CIrrDeviceLinux, but if SDL also uses XWarpPointer() to set the cursor position it won't help either. So I was looking at source of Minetest, specifically at this line of code: https://github.com/minetest/minetest/bl ... ra.cpp#L83
It uses a regular camera scene node and does not attach any animator to it (as far as I saw). If we take a look at the Camera::update() method, it's getting clear, that there is a lot of stuff going on to handle the camera movement/rotation.

So I guess, the bottom line is, that I need to implement my own camera movement/rotation just like Minetest does in order to provide a smooth camera movement/rotation on Linux.
Or are there any better directions to go for?

Anyway thanks for your hint, it was very enlightening :wink:
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Choppy FPS camera on Linux

Post by hendu »

You can start X with the "-schedInterval 1" option. The default is 5ms. Lowering the -schedMax from 15 to 5 or so could also help.

edit: And yes, SDL does the same. SDL2 on new X has a relative mouse option, but not SDL 1.
netpipe
Posts: 670
Joined: Fri Jun 06, 2008 12:50 pm
Location: Edmonton, Alberta, Canada
Contact:

Re: Choppy FPS camera on Linux

Post by netpipe »

not sure if it applies at quick glance, but the rendering draw ordering makes a huge difference for some things like physics and input.
Live long and phosphor!
-- https://github.com/netpipe/Luna Game Engine Status 95%
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Choppy FPS camera on Linux

Post by CuteAlien »

The problem without setPosition is that it only works while the mouse is inside the Window. There is a problem with X getting mouse-cursor position (XQueryPointer could cause freezes), not sure about setting it. But we already cache that call now (since Irrlicht 1.8).
Sorry I have no Wayland system so far, so I can't reproduce problems with that yet.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
est31
Posts: 14
Joined: Wed Sep 02, 2015 7:17 am

Re: Choppy FPS camera on Linux

Post by est31 »

In fact minetest has the same problem with wayland, reported as bug: https://github.com/minetest/minetest/issues/1763

TLDR: in the long term, wayland might implement a legacy solution that suits x11 applications like minetest, but until then, it will continue to not work.

If/when irrlicht supports to talk to wayland directly, then it could use the pointer confinement and relative pointer APIs:

https://cgit.freedesktop.org/wayland/we ... 1a0c4f0f9c
https://cgit.freedesktop.org/wayland/we ... 66879ea7fe
RungAaz
Posts: 11
Joined: Sat Jun 19, 2010 9:18 am

Re: Choppy FPS camera on Linux

Post by RungAaz »

Hey thank you all for you support, im back from vacation so I will try out some stuff.
You can start X with the "-schedInterval 1" option. The default is 5ms. Lowering the -schedMax from 15 to 5 or so could also help.
Unfortunately, starting X with "-schedInterval 1" didn't help, couldn't see any difference.


I recognized differences between multiple Quake3 maps. Or to be more precise, i found one Quake3 map that is "playable" with a smooth camera movement using the code from my first post.
The map is from the game "Zombles" (https://github.com/bwright/Zombles) - a game used for some Youtube tutorials - and can be downloaded: here.

If you compare this map with the Quake3 map provided in the Irrlicht examples using the Code i posted in the first post, you will see the difference in terms of "camera-smoothness".

Im not able to say why there is a difference, maybe because there is no "sky" in map zastavka_v13, since its like a cube ...
I will create two new very simple Quake3 maps:
* One, like a cube, where i spawn the camera inside the "cube"
* And one, that is like the first one, but where the cube is open at the top
I will compare those two maps and will post the results here
Post Reply