That seems like an easy straightforward way to do it… what are your problems with doing it like that?
I’m just trying to say that it really doesn’t matter, as long as things are going fast enough and are easy to use in the rest of your code. (Trying to do it ‘modular’ is good too, but in this case you could easily write a class that overloads the [] operator, if you’re into c++.)
If you have loads of bits (256 is not) then you could perhaps use std::vector<bool> which stores bools as bits (instead of taking up a byte, which is the common case) … but you’d lose a lot more performance trying to bit-fiddle like that than you’d gain by having a smaller memory footprint.
I started programming about 5+ years ago. During that time computers weren’t all that fast, and every book I read and every tutorial I saw have brain washed me into thinking “don’t use any more memory than you have to!!!”. In one way it’s helped me to keep things small, but in the other way it’s holding me from doing more things.
I’ll just have to get over it. You can’t push forward unless you push the limits.
Here’s an example of saving to much space. Way back when, when I had been programming for about 3 years, I had a cool idea for 3D models…it was to index vertices so you could share vertices that way. I said to myself “wow, all the indices would take up alota room in memory if I did that…the pros must have a better way”. Gah!!! If I had only pushed my limits. I’ve learned never to hold back sence I found out that that’s how the pros DO do it .
I believe the trade-off was the same then as it is now (I’ve coded in C/C++ for some 8 years now, and was hacking assembly on amiga before that).
Don’t optimize until you know it matters!
What if you optimize the heck out of this to save… say… 4 kb… only to allocate 200kb of stuff in another place… (and I’m being conservative with numbers here…)
[This message has been edited by macke (edited 04-16-2001).]
My <GL/gl.h> uses a lot of #defines and each of the GLenum variables is a 32-bit number (mine are typedef’d unsigned ints). Remember that because the numbers are 32-bits doesn’t mean there are 32 possible values that can be stored in them. Instead there are 2^32 possible values, or 4294967296. Bit patterns are a really good way to save space and store lots of information. For example, if you had a 3-bit variable, it could have 8 (not 3) different values: 000, 001, 010, 011, 100, 101, 110, 111
But you couldn’t easily see wether a feature is enabled or disabled.
But, hey, we’re inside states here. And I don’t think you’d have to check the states for every polygon as opengl drivers might have to do (btw: why do they have big switch statements, when they could alter their code?)… sO I’d think it is best to make it possible that the user can actually change the states easily.
Michael, you could easily test whether a feature is enabled or disabled with an inline function:
// Some hardcoded feature value. #define SOME_FEATURE 0xSOME_BIT_PATTERN
// Given some global state variable that
// holds the system state.
inline bool isFooEnabled()
{
if ((SOME_FEATURE & global_state_variable) == SOME_FEATURE) return true;
return false;
}
or even better:
inline GLenum isEnabled(GLenum state)
{
return SOME_FEATURE & global_state_variable;
}
// Which you could use like this:
…
if (GL_DEPTH_TEST == isEnabled(GL_DEPTH_TEST)) PerformAction();
…
// which would reduce the number of “if”
// statements required plus it would work
// for all the states in the system.
Hmmm, might implement something like this myself. Currently I’ve got a singleton system state manager with wrappers around a whole lot of OpenGL calls. I did this in response to a post of mcraigheads which said to manage system state yourself to avoid the overhead associated with redundant state changes.
ffish
But the use won’t be able to edit the values while the engine is running. That’s why I have runtime-variables.
If you do wrapping of opengl states, that what you propose os really ok!
Well, I was relating to variables that have nothing to do with opengl states . Just with engine states.
I’ll most probably use your thing to squeeze some performance out of it for opengl states
So… Thanx to YOU!
How about this for a solution.
Give each state a unique value. Create an array of 32-bit integers (how big of an array will depend on how many unique states you have. Then access bits like this:
unsigned int bits[100]; //holds 3200 bits
unsigend int stateArrayIndex(unsigend int state)
{
return (state >> 5);
};
unsigend int stateBitIndex(unsigend int state)
{
return (state & 0x0000001F);
};
void setStateBit(unsigned int state)
{
unsigned int index = stateArrayIndex(state);
unsigned int shift = stateBitIndex(state);
bits[index] |= (1 << shift);
}
void clearStateBit(unsigned int state)
{
unsigned int index = stateArrayIndex(state);
unsigned int shift = stateBitIndex(state);
bits[index] &= ~(1 << shift);
}
bool getStateBit(unsigned int state)
{
unsigned int index = stateArrayIndex(state);
unsigned int shift = stateBitIndex(state);
unsigned int bit = bits[index] & (1 << shift);
return (bit != 0);
}
This is how I would probably do it
Hey, I think you’re exagurating… After all it’s about little states! you can simply use a char for a state. We aren’T living in the time where we have to use only two digits for a date!
You can have 1024 states, and they will still be only 1kb…
And yours in slower then.
Of course, I should mention this only works for boolean states (glEnable/glDisable/glIsEnabled). Any state that has a value (like color has r,g,b,and a values) would have to be stored in its own variable. And to do something like glGetIntegerv, you would essentially have to do a giant switch statement, which is a killer for performance.
Actually, thinking about the switch, I wonder how good VC++ optimizes switch statements. If you have a switch with 1000 cases, I wonder if it does a binary search to find the case you need. I certainly hope it doesnt just plow right through them.
I’ll stick to my method but I like it LordKronos! Anything with obfuscating binary arithmetic must be good!
Seriously though, I guess the problem boils down to your second line: each state needs a unique value. The problem with the GL states is that there are so many of them that you can’t have a bit pattern that doesn’t overlap others. That’s why my inline functions above can query but not set.
Also, as you mentioned, your solution works for bools but not multivalued states My method (not posted) borrows (or copies) from the excellent Game Programming Gems book. I have a singleton class which wraps some OpenGL calls like glEnable/Disable etc, manages OpenGL states and copes with the multivalued states. As I said, the main reason I implemented this is in response to a post by mcraighead. It’s probably a bit (lot) slower than yours but more readable. I’ll keep yours in mind though.