My first post, Thank you for Irrlicht

Discussion about everything. New games, 3d math, development tips...
woalexan
Posts: 17
Joined: Wed May 28, 2025 6:22 pm
Location: Austria

My first post, Thank you for Irrlicht

Post by woalexan »

Hello,
as this is my first ever post in this forum, I wanted to take the opportunity to thank everybody that has ever contributed to this great project that Irrlicht is :D
I especially want to thank all people that after this long time still take care about this project, add new features and keep it running (for example CuteAlien). To be honest I have more of an electronics background, and four years ago I did not know much about 3D, vertices or SceneNodes. And then I was looking for a 3D Engine for my personal hobby project, found Irrlicht, went for it, and some years later I can say for sure it was a good choice :D

I am already 41 years old (time is unfortunetly flying), and I can still remember when I first played "Hi-Octane" from Bullfrog somewhere around the year 1995 at a 80486 computer at someones computer during a visit. I was completely blown away, I since then somehow this game always followed me during my live. Around 2010 when I was at the university I tried the first time if I could somehow recreate this game (at least partly) myself. I made a crude craft model in Blender, and was able to open it in a self written program. But I gave up pretty quick.

Around 2021 I was looking around the internet, and just by sheer luck I found out that around 2017 some people did reverse engineer most of the necessary file formats of the original game (HiOctaneTools project at Github). For me this was a real game changer, and I immediately decided to start another attempt to recreate this game myself somehow based on this new information. This is when I was also looking for a 3D library, and I found Irrlicht.

Of course initially I was really struggling (world coordinates vs. local coordinates, Meshbuffers ...), but I believe the design of Irrlicht really helped me to concentrate on the most important things (load models, move SceneNodes), instead of doing everything from Scratch.

Some years later I have a playable version of the game, but of course there are still many problems and bugs to fix, and many improvements to be made. Right now I have lightning of Irrlicht completely disabled, and I wanted to concentrate on the game mechanics first. After this is all set and done, I want to try to get the best possible graphics out from the old original games assets using Irrlicht. But before I can do this I still have to learn a lot of things about 3D, shadows, light, shaders and so on. But I also do not mind if this takes another more couple of years. It is my lifetime hobby project :D

If you want to check the project out, I made my Github repo public some days ago: https://github.com/woalexan/hi-octane202x

If you have any feedback, thoughts or ideas regarding Irrlicht and my project, please let me know. Thank you very much for any feedback, and thank you very much again for keeping this great project running :D
CuteAlien
Admin
Posts: 9970
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: My first post, Thank you for Irrlicht

Post by CuteAlien »

Welcome and that's quite the project.

Quick stuff I noticed - your string handling is a bit unnecessary complicated and expensive. And the main reason for that is that you often work with char* instead of const char*. Basically - unless you want to modify a string always work with const char*. Then you don't have to create copies like you often do with strdup (which is quite expensive). For example in your GameText class - all your functions can take const char* instead of char*.
And then intializing is also easier, you can just do: const char* someString = "stuff"; Which will create a read-only string literal.

If you really want to modify strings it's usually easier to work with a string-class. Either the one from the standard c++ library (STL) which would be std::string, or when working with Irrlicht you can also use irr::core::stringc instead (or std::wstring, irr::core::stringw for wide-chars when necessary).

Another thing I notice is that you often don't default-initialize pointers. This can make error-hunting a bit harder. Better to always initalize pointer variables. In modern c++ (which Irrlicht does not use yet, but don't let that stop you) you can do that directly in the header. But also for local variables like: EntityItem* nearestWayPoint;
I would always do: EntityItem* nearestWayPoint = nullptr; It's just something that will make debugging easier (because otherwise the pointers are randomly intialized - so you have no idea in the debugger if stuff failed or not).

Anyway, that's all I saw on a very quick view on the code.

Good luck with your project! If you have any questions, just post 'em in the forum.

Also you are still younger than most people involved with Irrlicht ;-)
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
woalexan
Posts: 17
Joined: Wed May 28, 2025 6:22 pm
Location: Austria

Re: My first post, Thank you for Irrlicht

Post by woalexan »

Hi CuteAlien,
Thank you very much that you took the extra time to quickly look at my project, for your answer and the recommendations. I really appreciate your effort, and all the feedback I received from you. It seems regarding Cpp I also still need to learn quite a lot, it shows that initially I had a microcontroller C background... I was not even aware that the NULL I know and I have used until now in the project was replaced by something better in Cpp. I will go ahead and fix this asap in the Repo :) I will also add it to all the uninitialized pointers in the header file for good measure.

Yes, also string handling is still a mess. When I started with the project some years ago I had not developed C for 9 years, and so the first source code parts looked horrible (char* stuff and a lot of strcpy). Thankfully a friend of mine cleaned up some of my code at one point in time, and he introduced me to the strdup command, to convert the const char* things to char* that some underlaying code relied on (source code that was developed by somebody else, for example to unpack RNC). And then I took over strdup for other places as well, which maybe was not the best choice. Maybe I should change everything to std::string or your other recommendations one day.

I still believe at some point in time I have to rewrite huge parts of my work anyway (for example for mulitplayer, or a possible level editor), but I also have no problem with this :) Hobby projects do not immediately need to be finished. And then the new code hopefully will be much better again.

I was wondering one other thing, if I may ask quickly: If I "stack" more and more "->" to access something from one class to the other (I known data in objects should normally be encapsulated :), but I have a lot of stuff still public to access it easier) I guess there will be also a speed penalty with each "->", or? Because I guess each "->" translates to an additional indirect adressing operation in assembler, or I am wrong? Which will use additional clock cycles.

Likes this here: this->mLevelTerrain->DynamicTerrainSceneNode->setTriangleSelector(triangleSelectorDynamicTerrain);

Performance is right now not such an issue, at my Ryzen 5 3600 CPU and the single core that is used it produces > 500 FPS when VSYNC is disabled. But your feedback is very useful for me, to hopefully become a better Cpp programmer one day.
CuteAlien
Admin
Posts: 9970
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: My first post, Thank you for Irrlicht

Post by CuteAlien »

There is a bit a of a speed penalty when working with pointers. Thought mostly due to cache misses (processor can't guess which memory is accessed next). But there's not many cases where you will notice this. So I wouldn't worry about that. String allocations at runtime on the other hand can be noticed a lot faster because they involve allocating heap memory and that isn't so cheap (doing it a few dozen times still hardly matters, but doing that hundreds of times it'll quickly become a bottleneck, so best to avoid it whenever you can).

And yeah, the nullptr is relatively new (introduced 14 years ago .... not used yet in Irrlicht ^_^) .
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
woalexan
Posts: 17
Joined: Wed May 28, 2025 6:22 pm
Location: Austria

Re: My first post, Thank you for Irrlicht

Post by woalexan »

Thank you again for your answer to my question. I am glad that the speed penalty with using the pointers like in my example above seems to be small enough, so that I can keep working like this. I already read some information about nullptr in the internet over the weekend, and as soon as there is time I will fix it everywhere possible. I will need to change a lot of project files.
Today I tried to improve the computer player control again in combination with the charging stations in the levels. I made good progress, but I think one of the most challenging things about this project is the level design. Their level design choices changed a lot over the different levels, and some source code that works for the first 4 levels, could stop working in level 5, or the one single charging station in level 6 :( It is really annoying.
But one day it will all work for sure...
I wish you all a good start into the new work week.
woalexan
Posts: 17
Joined: Wed May 28, 2025 6:22 pm
Location: Austria

Re: My first post, Thank you for Irrlicht

Post by woalexan »

Hello, in the mean time I introduced the nullptr instead NULL in my project everywhere, and it caused no issues at all. Thanks for pointing this out again. I also learned during the last days that I had done the includes in my projext as horrible as only possible. I always thought it is a good idea to put all includes into the header file.... O boy was I wrong :) I mean it was working ok, but when I tried to change stuff around again I caused a lot of new include problems.
And then I learned that I should only put the absolute (necessary) amout of includes into each header-File to make it work, only utilize forward declaration to classes that I use with pointers later, and so on, and later only put all necessary includes into the CPP file at the top. Yesterday I spent a whole day to fix this mess I created in the first place :) (This changes are not yet reflected in the Git repo, only in my local branch)

But yesterday I had another issue which I do not understand... When I create a "addCameraSceneNodeFPS" camera, and I currently have it set as the active camera (so that I can move it around actively) every time I call getAbsolutePosition on this camera I basically get a position in the origin (0.0f, 0.0f, 0.0f). The camera seems to be always in this origin position. But when I have a second FPS camera, and I set this one to active then suddently the first FPS camera getAbsolutePosition call delivers as expected the current absolute position of this camera node. Is this to be expected? If so why?

I also tried to create (an invisible) SceneNode which parent is this first FPS camera, and then tried to get the position of this SceneNode instead. But also this does not work, I again get the origin in case the first FPS camera is active.

I really need the absolute (world) position of this FPS camera for a ray starting point, but I do not understand anymore what is going on. Thank you very much for any help.
CuteAlien
Admin
Posts: 9970
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: My first post, Thank you for Irrlicht

Post by CuteAlien »

Irrlicht caches updates to absolute positions for all scene nodes as the operation to calculate those is a bit expensive. So if you try to get that value outside the usual render-loop then it's behind by 1 frame. You can force calculating it with updateAbsolutePosition(). Or just put your camera on the top (rarely a reason to not have it on top), then you can use getPosition instead (which is the position relative to the parent - but when it has no parents those are identical).
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
woalexan
Posts: 17
Joined: Wed May 28, 2025 6:22 pm
Location: Austria

Re: My first post, Thank you for Irrlicht

Post by woalexan »

Thank you very much for your fast response. My problem is not that the position I get with getAbsolutePositiin or getPosition from the FPS camera is in the origin for the first frame, it is in the origin the whole time (all frames). I also ran updateAbsolutePosition before, and it did not change the behavior. I thought it maybe has to do with the way this camera is implemented in the first place, but was not sure. I only know if the camera is not set to active anymore it returns the expected position. I guess without any source code its difficult too help.
woalexan
Posts: 17
Joined: Wed May 28, 2025 6:22 pm
Location: Austria

Re: My first post, Thank you for Irrlicht

Post by woalexan »

I forgot to mention I have the same problem when I try to use getRayFromScreenCoordinates; According to the documentation the ray start should be at the location of the currently active camera (which in my case is the FPS camera), but also here the returned ray.start location is always at the origin (0.0f, 0.0f, 0.0f); The ray.end location seems to be correct (does change with the position of the mouse cursor I use for the screen coordinate input); I run this command (and the camera getPosition commands) within the game loop, somewhere before the mDriver->beginScene() command. After I had no luck with the getRayFromScreenCoordinates command, I started my own experiments with the camera->getPosition() and getAbsolutePosition command, and found out that I have no luck with it as well.
CuteAlien
Admin
Posts: 9970
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: My first post, Thank you for Irrlicht

Post by CuteAlien »

That's strange - but your sources are online. Can you tell me where (file, line) you are checking for the camera position? Maybe I can see something by taking a look.

edit: Also something else I noticed when taking a look at your sources. Irrlicht's memory management is a bit non-standard in C++. You work with delete a lot for Irrlicht pointers and that's nearly always dangerous. The reason is that Irrlicht uses reference counting for it's dynamic objects. Best take a look at this: https://irrlicht.sourceforge.io/docu/cl ... unted.html
If you just call delete the risk is very high that the object will get double-deleted which can have all kind of strange effects from crashes, to completely unexpected behaviors.
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
woalexan
Posts: 17
Joined: Wed May 28, 2025 6:22 pm
Location: Austria

Re: My first post, Thank you for Irrlicht

Post by woalexan »

My problem with the camera occurs in the new level editor executable which I started only some days ago. This source code is not yet merged into the main branch of my repo, and therefore you will not find it there. I changed a lot of things again for the editor, and therefore I wanted to test everything in Windows before I merge it. For example I do not yet know if Visualstudio and MSVC will accept my new CMakefike. I will try to do this in the next 2 days, if succesfull will do the merge into my repo, and if I may (and you have some time left) tell you about the exact location in the updated project. Thank you very much for looking into the available sources already, and for the information regarding delete. And sorry that you had no chance to find it in the current state of the repo.
woalexan
Posts: 17
Joined: Wed May 28, 2025 6:22 pm
Location: Austria

Re: My first post, Thank you for Irrlicht

Post by woalexan »

I tried a little bit more, and I was clearly wrong until now. The camera returns the expected current position. So the camera is not the problem. Maybe I have a line3D drawing issue. When I draw a 3Dline starting from the cameras position is it then clipped and not shown on screen?
CuteAlien
Admin
Posts: 9970
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: My first post, Thank you for Irrlicht

Post by CuteAlien »

Hm, there's 2 typical things people mess up, maybe one of those is your problem:

First check docs of draw3DLine: https://irrlicht.sourceforge.io/docu/cl ... 3a4eebb5e6
You have to set the correct material and transformation before IVideoDriver draw functions. And for line materials it generally makes sense to disable lighting in the material or things get a bit more complicated.

The other bug many people make is trying to draw lines from the camera position to some target in the camera view direction. But... that's just a point. Bit like looking at a finger while sticking it into your eye ;-)
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
woalexan
Posts: 17
Joined: Wed May 28, 2025 6:22 pm
Location: Austria

Re: My first post, Thank you for Irrlicht

Post by woalexan »

Hi CuteAlien,
Thank you for your valueable input, in my case it was the second bug you suggested... so the problem was me, and I feel like an idiot now :) Most likely it was working already most of the time (during my several hours debugging session), but I kept wondering why I do not see any line... I never thought about the fact that the line is a point as you described :) And add also some smaller mistakes and the confusion is perfect.

Now I got it working nicely, I can select terrain tiles and faces of colum blocks with my FPS camera and mouse cursor. On top of that I managed to get my first Irrlicht Gui Dialog for terrain texturing working as well. And now I am stuck at a very tricky part again, the part which I feared most from the beginning: Which is swapping out triangles in the SMesh of the Terrain SceneNode, after the user decided to change a texture of a terrain tile in the level editor.

My setup is: The (tile map) terrain has up to 256 different textures. For each texture I initially create a SMeshBuffer buffer (for each terrain texture). I do not drop any of this buffers, I keep pointers to them for later changes. For each material I then create the existing triangles with this material in the SMeshBuffer. Afterwards all SMeshBuffers that have at least 1 triangle are added to a SMesh for the terrain. This SMesh is then used to create an "addMeshSceneNode" for drawing the terrain. For collision detection in the game and for ray intersection in the level Editor I also create an "createOctreeTriangleSelector" based on this SceneNode. And I use "setTriangleSelector" of this SceneNode to point back to the triangle selector.

When the user does decide to change a tile texture, I go into the initial SMeshBuffers that we created for the texture before the change, and remove the tile vertex indices from the SMeshBuffers, so that the tile with the old texture disappears from the terrain Mesh. This works well for all cases.

Then I go into the SMeshBuffer for the new selected texture, and add the vertice indices for the tile back, which texture was changed. In the case the material/texture was already used before in the level this step works also well, and the new tile with the new texture appears again in the level editor Terrain. No crash occurs here.

But in case the texture was not yet used, I take the initially created SMeshBuffer for this newly selected texture/material (which is at this point in time still not added to the SceneNode Mesh), add all terrain vertices to it, and add 6 new vertice indices for the changed tile to it. And then I finally add this SMeshBuffer to the Terrain SceneNode, and mark everything as dirty. Problem is afterwards "mSmgr->drawAll();" in my gameloop crashes immediately :(
If I instead add this newly created tile SMeshbuffer to an independent new "test" SMesh and test SceneNode no crash occurs, and the newly created tile also occurs in the level editor. So it seems my new updated SMeshbuffer is also done correctly (vertices, indices seem to be correct).

Is it even allowed to add an additional SMeshBuffer to a SMesh and SceneNode that is already in use by the level editor? As I said on top of it I also have a triangleSelector running on it... Maybe this is not supported?

Thank you again in advance for any hints, I know this is a very tricky problem, and most likely a poor description of my problem :( I will also need to push my latest changes to the GitHub repo.

Have a great day.
woalexan
Posts: 17
Joined: Wed May 28, 2025 6:22 pm
Location: Austria

Re: My first post, Thank you for Irrlicht

Post by woalexan »

All my latest changes over the last 3 weeks (including the first steps of the level editor and the bug that leads to the crash) are now merged and commited into main of my projects git repo. Just in case somebody wants to look at it :) But to be honest I believe my source code around this terrain mesh creation is way to messy to be viewed, understood and fixed in an acceptable amount of time.
Post Reply