New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Review phase] Terrain texture selection #1769
Conversation
And here we reach the point where not having scrawl around really hurts, because I am not familiar with this stuff either. Anyway, I did a test run and ended up with a segfault on attempting to select terrain: https://gist.github.com/zinnschlag/0916aa134ae01a2484ed24f7f5faef9d |
Get in the habit of using WIP in stead of Don't Merge :) |
I know that @kcat has some experience with terrain... perhaps he can help review? |
I haven't got any segfaults, was there anything specific you were doing, or just clicking primary select? I don't really know how to read that gistfile, but looks like activate-function doing something with Qt. I really don't know... Version mismatch? I'm using Qt version 5.11.0 I'll try to click everywhere and see if I can get a segfault somehow. (edit: I can't find a way to crash it) |
Just random clicking. Still on Qt 4, but from the stack backtrace it is pretty clear that this is not a Qt problem. |
This looks highly suspicious. Just saying. |
I'm not particularly familiar with terrain-related stuff. Especially on the editor side of things. |
@zinnschlag what file(s) are you loading to trigger this? That stacktrace looks like something in the loadland code. |
Morrowind.esm. I doubt that it is the load code itself. Notice the this value? Very unusual. Could be a multi-threading problem or maybe an object life-time problem. Only guessing here. |
Qt4 uses threaded renderer whilet Qt5 uses single-threaded renderer... not sure if that makes a difference? |
Not really. I was speaking about threading in our terrain system. |
Apparently nobody (including me) noticed the elephant in the room: Why is it trying to load terrain when I select a piece of terrain? Obviously the terrain was already loaded. Otherwise it could not have been rendered which means I couldn't have clicked on it to select it. |
Could be your click was interpreted as a being in one of the unloaded cells. Maybe try moving away from loaded cells and try reproducing it. I think the worldpos returned defaults to a set distance when nothing gets clicked on. (Unloaded cells just aren't rendered iirc). |
Lol. I compiled your code again and then noticed the warning:
So, yeah. One of my guesses turned out to be right. Object life-time issue. |
I'm trying to reproduce or understand the issue, but I don't get any errors, warnings or crashes, and furthermore, I'm clueless why mCoords would persist only until the constructor exits, as to my understanding it's defined in terrainselection.hpp correctly. If this is clear, I'd be really grateful if someone could explain this to me. I've stopped development until this is resolved. I don't know how to approach this problem, as Zini's comments are only info I have of this, and I can't understand a problem in the code. There are some other glitches too, but crashing is so fundamental that it's probably better fixed first. There's a noticeable offset from selection grid to actual world texture grid, and cell borders don't operate/render correctly. Drag-select is also still missing. |
What platform are you guys on? Windows, Linux or MacOS? Could be a difference in compilers... msvc vs gcc vs clang? |
Linux *** 4.9.107-2-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux |
That you don't get the crash isn't surprising, because undefined behaviour. However that you don't get a warning message is surprising. Anyway, an easy fix would be to change mCoors from const CSMWorld::CellCoordinates& to simply CellCoordinates. Reference as member variables are rather strange to begin with. Not outright wrong, but most of the time a bad idea. Still trying to track down the source of the problem would be a good idea. |
Just to make this clear: It is not mCoors (because mCoors is a reference). The compiler is complaining about a temporary that is bound to mCoors. |
To be sure, I compiled it again from the start, and searched the log for that warning, and keywords (terrainselect.cpp) etc. but found no warnings related to this. I don't really understand when using references or pointers is good/bad, but I didn't change anything that didn't work. Thanks for clarification anyway, it gives me at least one place to look. |
Compiler bug: https://stackoverflow.com/questions/10509603/why-cant-i-initialize-a-reference-in-an-initializer-list-with-uniform-initializ I'm guessing Zini is using gcc 4. Use regular initialization to work around it. |
@zinnschlag if you're toolchain is buggy, time to upgrade ;) |
4.8.4. And not upgrading yet (too much stuff that would break and absolutely no time to deal with that). |
The code is not written by me, and I'm still fairly beginner in C++, so I'm going to milk some knowledge out of you to fix this, and learn. So, am I understanding this correctly? Because of C++ compiler bug/feature, there's some undefined behavior occurring from list-initialization in format: variable {parameter} and that would be fixed by using "default initialization" in format: variable (parameter)? The former should work in C++11, but not necessarily in C++ versions before that? Does this mean that list-initialization cannot be used at all in OpenMW? In addition, I don't see any advantages for using initializer-list with only one parameter. Is this true? And fundamentally, I'm understanding that initializer list (member initializer list) is a different thing than list-initialization? Former is the thing happening after : in constructor, and latter is something like variable {}. To the problem at hand, the problem seems to be affecting mCoords, as it's initialized with a parameter that is a reference. In this case, CSMWorld::CellCoordinates& coords instead of CSMWorld::CellCoordinates coords? I also don't see any advantages in using a reference here. The full initialization list where the problem occurs also initializes variables mEsmLand {esmLand} and mParentNode {parentNode}, of which mEsmLand is a reference. Shouldn't that be changed also? Do I need to change both - the list-initialization to default initialization, and references to default variables? |
I am not entirely sure if that is what is happening here (since the error message is noticeable different from what I am getting). But it is worth a try.
The former is a C++11 feature. It did not exist before C++11.
The initiliser-list is nearly always preferable over initilaising in the function body. Its cleaner, for some types it avoids redundant initialisation and for other types it is mandatory.
The problem is not the parameter. The problem is the variable itself. mCoors should not be a reference. Let me reiterate that: Having a reference as a class member variable is usually a bad idea. It is not outright wrong (there are certainly situation where I have used them in the past), but there is typically little benefit to it and a couple of potential disadvantages (objects of the class become un-assignable for example). I would also argue that it is somewhat counter-idiomatic.
You can not simply remove the reference, because that would make a copy and that would be wrong in this case. However using a pointer instead of a reference would express the intend more clearly. C++ does not have the concept of value and reference types (as in languages like C#). But CellCoordinates comes pretty close to a value type, while ESM::Land (in this context) is pretty close to a reference type. |
Initializer list is an ambiguous term. https://en.cppreference.com/w/cpp/utility/initializer_list Using {} over () is purely personal preference unless using initializing a vector, list, etc. with data. Here the c++ 11 standard was amended and gcc4 implements the original behavior. |
I ran into error message "no match for 'operator*" when backtracking and changing the reference of mCoords to a pointer, in mcoordinates in cell.cpp line 147. ( https://github.com/unelsson/openmw/blob/5419f4427b66302c2a3f37be751981804fd33b77/apps/opencs/view/render/cell.cpp#L147 ). There's still a reference as a member variable... Anyway, changed the {} to () and tested, on my computer it works without crashing as it did before. |
Nope. Not mCoors. As mentioned above that is as close as possible to a value type as something in C++ can be. Store it by value and pass it by reference. |
While digging into what's a pointer and what's a reference and what to do, I encountered another thing I didn't understand: What would be the point in auto and static_cast at terrainselection.ccp lines 59-60 & 67-68?
Couldn't that be as well just normal conversion from double to int?
|
Initialization {} to auto = static_cast.
58c201e
to
ff6a41b
Compare
Tried to rebase, got into trouble with merge conflicts, which resulted in total destruction. |
Terrain texture selection, based on #1414
Feedback and review is greatly appreciated. Plutonicoverkill's code had some reviews, but I don't clearly understand what are the reasonings behind those comments.