zombe on 29/12/2011 at 16:56
I have got a mysterious warning/error with c++ ... granted, i am kind of tired and probably messed up something embarrassing, but wtf is going on here:
int32u *cellData[9][3]; // int32u is just a basic 4byte unsigned integer type
int32u const **cellDataZ = &cellData[(int32u(-2+16) >> 4) * 3 + (int32u(y+16) >> 4)][0]; // y is int32 type (ie, signed)
Last line gives:
warning C4554: '>>' : check operator precedence for possible error; use parentheses to clarify precedence
error C2440: 'initializing' : cannot convert from 'int32u **' to 'const int32u **' (Conversion loses qualifiers)
Neither makes any sense to me. Dropping the const takes care of the first and writing "(int32u(-2+16) >> 4)" as "((int32u(-2+16)) >> 4)" takes care of the other - so, not a show stopper, but i would like to know what is going on there.
PS. instead of conversion constructor function-style cast i can also use "((int32u)(-2+16) >> 4)" and let the operator precedence rules do the deed.
"(int32u(y+16) >> 4)" is fine without changes => which makes me suspect there is some compiler bug involved. What do you think?
PS2. This is with VC++ 2010.
Al_B on 29/12/2011 at 18:50
Ignore original reply - now had a chance to check it in VC++ 2010 myself.
I think the first warning is simply because the compiler is making sure that you didn't mean to write something like "int32u(-2) + 16 >> 4" when you used two constants together. I assume you're using preprocessor defines for the -2 and 16 magic values as otherwise it would be unusual to hard code them in the line like that. As you say - using the old C-style cast avoids the warning as does simply adding another set of brackets either outside the function cast as you've put above or inside - i.e. (int32u((-2 + 16)) >> 4) also works. In either case, the compiler appears to generate the correct code so it's more informational than anything else.
For the const problem - do you want the cellDataZ variable itself to be constant? If so, I think you want "int32u ** const cellDataZ = ..." - i.e. with the const just before the variable name? Otherwise you'll need to declare cellData itself as const to work in the manner as you've originally written it.
zombe on 30/12/2011 at 00:48
Quote Posted by Al_B
I think the first warning is simply because the compiler is making sure that you didn't mean to write something like "int32u(-2) + 16 >> 4" when you used two constants together.
Hm, writing "int32u((-2 + 16))" also fixes it - i think you are right. VC likes (thankfully actually) to warn about stuff near << and >> as their precedence is a bit peculiar (not seeing it as justified in this particular instance tho).
Quote Posted by Al_B
I assume you're using preprocessor defines for the -2 and 16 magic values as otherwise it would be unusual to hard code them in the line like that.
The magic values are not magic in their context and are written the way they are to be clear about the intent and meaning of it (there are many lines similar to it and all use the same form).
Quote Posted by Al_B
In either case, the compiler appears to generate the correct code so it's more informational than anything else.
Yeah, assumed as much (it is just a warning - the is no actual ambiguity) - just never seen it warn about this kind of code.
Quote Posted by Al_B
For the const problem - do you want the cellDataZ variable itself to be constant? If so, I think you want "int32u ** const cellDataZ = ..." - i.e. with the const just before the variable name? Otherwise you'll need to declare cellData itself as const to work in the manner as you've originally written it.
I have a habit of using "const" quite aggressively - at that time i was adding const for all the stuff referencing the int32u data itself. The correct constness for the stuff is (which i actually use. the previous code was the mysterious wtf i got while in progress of fixing the constness):
int32u const *cellData[9][3];
int32u const * const * cellDataZ;
// PS. i always use "type const" instead of "const type" for consistency (the "const type" exception is only usable with the "type" part and nowhere else).
However, i still do not get why it failed with the code presented originally. Still a mystery :/
----------------------
Yay, progress:
Inline Image:
http://img545.imageshack.us/img545/5967/newalgsimplex.pngPretty darn fast tesselation (*) of 16x16x16 chunked map. Smoothed plain and simple cubes (ie. not generated using marching cubes alg). Vertices are shared (using "glDrawRangeElementsBaseVertex" for drawing). Full adjacency information for normal generation (chunk borders inclusive - something i forgot to take into account the first time around) - currently not generating the normals tho.
(*) Avg. 120 ticks per voxel for the given map - expecting that to triple-quadruple when i am finished with it.
edit: Ah, forgot to mention, there are 2 lines per voxel per axis on the pic - just to give an idea how big the voxels are.
Al_B on 30/12/2011 at 02:40
Quote Posted by zombe
I have a habit of using "const" quite aggressively - at that time i was adding const for all the stuff referencing the int32u data itself.
I'm not a huge fan of const although it obviously has its benefits. When you start dealing with double (or higher) level indirections it just seems a little easy to end up with issues like you came across.
Quote Posted by zombe
However, i still do not get why it failed with the code presented originally. Still a mystery :/
With your original code you'd be able to assign a value to *cellDataZ which could be used to modify constant values. As a simple example - I'm sure you accept that this is invalid:
Code:
int const MeaningOfLife = 42; // Answer to the meaning of life - must never change
int *NonConstPtr = &MeaningOfLife; // Not allowed because ...
*NonConstPtr = 54; // ... this could happen (oops)
The equivalent with your code would allow the same thing to be done by a slightly longer route:
Code:
int const MeaningOfLife = 42; // Answer to the meaning of life - must never change
int *NonConstPtr;
const int **SomeConstPtr = &NonConstPtr;// Equivalent to your error - compiler will complain
*SomeConstPtr = &MeaningOfLife; // Perfectly legal - NonConstPtr now points to MeaningOfLife
*NonConstPtr = 54; // Also legal (Oops again)
It's not likely you would write code that would do that - but as it's possible it is simply disallowed.
Quote Posted by zombe
Yay, progress:
Pretty darn fast tesselation (*) of 16x16x16 chunked map.
Looking interesting - will be good to see it when you've got some alternative textures on it (assuming you're not going for the psychedelic vibe!)
zombe on 30/12/2011 at 12:43
Quote Posted by Al_B
I'm not a huge fan of const although it obviously has its benefits. When you start dealing with double (or higher) level indirections it just seems a little easy to end up with issues like you came across.
Const helps the compiler considerably (+ __restrict__ where needed) and sometimes prevent me from shooting my legs off. True, sometimes the compiler spots some pesky distinction i do not particularly care about, which is a bit annoying, but it happen very-very rarely.
Quote Posted by Al_B
As a simple example - I'm sure you accept that this is invalid:
Yes. NonConstPtr is of type "int *" and at the right side is "int const *" => attempted breach of const contract.
Quote Posted by Al_B
int const MeaningOfLife = 42;
int *NonConstPtr;
const int **SomeConstPtr = &NonConstPtr;
*SomeConstPtr = &MeaningOfLife;
*NonConstPtr = 54;
Yep - good example. Aliasing issue - and as compiler can not possibly detect such problems at compile time => it assumes the worst. Mystery solved. :thumb:
Quote Posted by Al_B
Looking interesting - will be good to see it when you've got some alternative textures on it (assuming you're not going for the psychedelic vibe!)
Hehe, psychedelic vibe is not the goal (1). Speaking of textures: that is just a shader - have not written any texture loading yet. Low priority (2). I am more worried with other stuff (3).
(1) Used that for testing - easier to see how things are smoothed and sport problem cases. Speaking of which - having the whole resource system built with "hot-swap" capabilities (any external changes to any resource files will take effect immediately in game and problems reported in log [Using an xhtml/javasript logViewer that auto-updates / prettifies etc + auto-scrolling option {defaults to it whenever it detects a new logging session}]). Adjusting the shaders etc/without needing to restart nor manually reload them => is just totally made of WIN! Highly recommended.
(2) Currently it just ignores block material and piles it all in default-material mesh assembly - fairly trivial to add other materials as the renderer already handles all the state sorting/combining (where needed) etc.
(3) Considerable obstacles i want to ensure i can reasonably solve before i delve into easier issues:
* Physics: should be relatively simple ... erm, physics never are. Quite optimistic with it tho (at the midpoint of tessellation i have the needed data in a form that is fairly compact and still in "physics" friendly state - ie, before it gets bastardized by mesh generation).
* Lighting: i need 4 directional ambient lights ("ambient" as in minecraft which has 2 non-directional ambient lights) - updating thous will be painful and highly worrying.
* World gen (currently just glm::gtx::noise::simplex(pos*scale) > 0.0f for testing): i do not want to use anything that uses floats as i need guarantees that given the exact same input i will get the same output. Floats simply cannot do that (One can set the FPU flags/state to some fixed state and prey [yeah, from personal experience, not fun figuring out who changed it] no-one else fiddles with it. Disable all FP optimization and force it to write out all intermediate values => x_x). I have some ideas tho ... will see.
Al_B on 30/12/2011 at 14:20
Quote Posted by zombe
Const helps the compiler considerably (+ __restrict__ where needed) and sometimes prevent me from shooting my legs off.
It's a personal choice. It probably makes little (or no) difference to the compiler since there are many circumstances where it can't assume that the variable really is const. However, modern compilers are fantastic at optimising and will probably treat something as const even if a variable isn't declared that way. I totally agree they can be useful in catching human errors (mine included) but having to fire up my brain to work out what "int const ** const x" does and doesn't allow to be done with x is more likely to make me miss larger problems with code.
Of course - all that is subject to profiling. If your code bottlenecks have benefited from const'ifying the variables then I'm certainly not going to argue against doing it!
Quote Posted by zombe
having the whole resource system built with "hot-swap" capabilities (any external changes to any resource files will take effect immediately in game and problems reported in log [Using an xhtml/javasript logViewer that auto-updates / prettifies etc + auto-scrolling option {defaults to it whenever it detects a new logging session}]). Adjusting the shaders etc/without needing to restart nor manually reload them => is just totally made of WIN! Highly recommended.
Very nice indeed. I can see that saving you a lot of time in the long run and it sounds like you've got an ideal testbed for quickly knocking something up in future.
Quote Posted by zombe
i do not want to use anything that uses floats as i need guarantees that given the exact same input i will get the same output. Floats simply cannot do that
Agreed - at least not in a guaranteed cross-platform way. Have you considered simply using fixed point for what you need? You'll obviously have to choose the scale of your precision but since you have a fixed world granularity it would appear at first glance to be a reasonable option.
Bakerman on 31/12/2011 at 14:01
Quote Posted by zombe
Pretty darn fast tesselation (*) of 16x16x16 chunked map. Smoothed plain and simple cubes (ie. not generated using marching cubes alg). Vertices are shared (using "glDrawRangeElementsBaseVertex" for drawing).
Very cool stuff. Forgive me if you've mentioned before, but where are you heading with it? I can imagine some very cool Descent-like 3D combat. Possibly even a sort of corridor-crawling Shattered Horizons.
zombe on 31/12/2011 at 20:37
VC2010 does not accept: "void (*p)(void *) = [](void *) {};" => me is not a happy bunny :(
(
https://connect.microsoft.com/VisualStudio/feedback/details/572138) Apparently have to wait till the next version of VC gets released for a fix. Unless the workaround is any good (have not yet dug into that).
Hm, since i switched from VC2008 to VS2010 relatively recently, might share my impressions for thous who have not yet switched (my -10..10 point scale grade):
* IDE is incredibly slow to start up. (-1p)
* slowness from excessive HDD accesses (-2p)
* "go to definition" and other searches are (most of the time) actually working (vs. just giving a few pages of random and completely unrelated garbage)!!! holy shit! (+7p)
* intellisense - hell yeah, MAJOR time saver! (+11p)
* intellisense causes the whole IDE to crash ever now and then. (-2p)
* intellisense gets nuts every now and then - underlining everything with bogus errors. switching to some source file added in solution explorer for a moment does fix it luckily. (-1p)
* bogus warnings one can not turn off in compilation script (script is per installation and not per project unfortunately) - had to edit it. (-1p)
* quite a few C++0x stuff is implemented (+4p)
My conclusion, with the benefit of hindsight => well worth the trouble porting the projects.
Quote Posted by Al_B
Agreed - at least not in a guaranteed cross-platform way. Have you considered simply using fixed point for what you need? You'll obviously have to choose the scale of your precision but since you have a fixed world granularity it would appear at first glance to be a reasonable option.
Yep, considered that. Googled various implementations etc, but the complexity of divisions / multiplications is offputting :( Most divisions/multiplications one can simplify considerably (tried that with simplex noise - just to see how it goes with some real case math) - but not all. Not happy with it.
Quote Posted by Bakerman
Very cool stuff. Forgive me if you've mentioned before, but where are you heading with it? I can imagine some very cool Descent-like 3D combat. Possibly even a sort of corridor-crawling Shattered Horizons.
That actually depends a bit on how some of the things work out. My calculator told me that the thing i originally wanted to do i just can not do with current hardware limits - so, it is a (HUGE) compromise, and hence i am not sure how it works out (ie. what MORE i have to drop and/or change). Do not quite want to jinks it yet ... will know better what path i have to go when i know the limits.
Al_B on 31/12/2011 at 23:50
Quote Posted by zombe
VC2010 does not accept: "void (*p)(void *) = [](void *) {};" => me is not a happy bunny :(
I don't think you can be too harsh on VC2010 for that one - C++11 is pretty new. Why not just give it an address of a placeholder non-lambda function if that's what you need?
Quote Posted by zombe
Yep, considered that. Googled various implementations etc, but the complexity of divisions / multiplications is offputting
In practice all you need to do is effectively a bit shift before or after a regular integer multiplication or division. You obviously want to do it in a way that preserves precision but there are examples online on how to do it. It won't necessarily be quicker than floating point but the repeatability of results will be better and I doubt it will be the bottleneck in what you're doing.