Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 22 Aug 2001
Offline Last Active Nov 26 2015 11:12 PM

#5259686 NonCopyable everywhere ?

Posted by Trienco on 29 October 2015 - 11:29 PM

The main reason is usually doing things like having "new" in the constructor and "delete" in the destructor. Any accidental temporary copy would typically cause a double delete eventually (or worse, leave your original with an invalid pointer for a long time, only crashing much later and being a real pain to debug).


One solution is explicitly deleting all problem operations (assignment, copy construction, etc.)


A typically better solution is to properly express your ownerships by using the correct smart pointer. In the above case, use a unique_ptr instead of a raw pointer and suddenly code that would accidentally (or intentionally) copy or assign won't compile. Problem solved without messing about with deleting default functions. If data should be shared, use a shared_ptr and data is automatically deleted at the proper point. In both cases, you don't need to worry about manually deleting anything.


Just making literally everything noncopyable for no good reason would simply look like unreflected cargo cult programming (yes, it's a thing and scarily common).

#5249106 Problem when compiling SFML game with Code::Blocks

Posted by Trienco on 26 August 2015 - 10:12 PM

That's exactly the same problem, except you apparently changed from static linking to dynamic linking. All your changed build option did was to move the error from compile time to run time.

SFML is trying to call a function that is missing in your version of the standard library. The first step when you get linker errors about stuff being undefined is to copy paste the error (or at least the symbol it complains about) into a search engine (unless you already know which library or source file contains the missing code). All results are the same: you need at least GCC 4.9.

From the fact you HAVE SFML libraries and the error you see now, I would assume you didn't build SFML yourself and just grabbed some pre-built binaries. Those were built with a newer version of GCC and the simplified issue is: it's not compatible with yours (technically the problem is more with the different standard library versions).


Since you're on Windows anyway and struggling with very common compiler/linker errors: why are you adding the extra pain and complexity of using an IDE that uses MinGW instead of some Visual Studio Express or Community version? Dealing with the extra issues from potentially outdated GNU ports for Windows is not something I'd do without a very good reason.

#5247693 Quaternions for FPS Camera?

Posted by Trienco on 19 August 2015 - 10:22 AM

Just quickly going over it:
Yes, when you move (especially along local axes), your orientation is relevant.
You won't get anywhere with just your cameras position. A direction means you have a "from" and a "to". To get a view vector from your camera position, you ALSO need the position of whatever you want to look at. If you use a rotation matrix to store the camera orientation, your view vector has nothing to do with the position and is typically the "forward" part (ie. the third column of your rotation matrix).
I think one problem might be that you don't know what to do with those values you are trying to compute. So the basic question before all others is: how do you intend to set up your view? Will you add the view matrix to the transformation stack, specify it separately through an API call or do you plan to use some helper function like "lookAt"?
Uhm, yes. East should be west. That was me being directionally challenged.
If you don't plan to write your own shaders, the w coordinate shouldn't be something to worry about.
Matrices are a bit painful to display (there's also lots of arbitrary decisions that can be made by the API, engine, or yourself). Usually, the matrix is stored as an array of 16 values, the first four being the first column, the next four being the second, etc. The "mathematical" representation would look something like this (with r=right, u=up, f=forward, p=position):
r.x | u.x | f.x | p.x
r.y | u.y | f.y | p.y
r.z | u.z | f.z | p.z
0   | 0   | 0   | 1
Of course you might use completely different conventions. In a top-down game, the y-axis might be forward and z would be up.
If movement is going the wrong way, try moving along different axes. Chances are you're simply not looking at the object from the direction you think are. With a right handed coordinate system, "forward" is -z, but the default is the identity matrix (so your camera wouldn't be facing "into" the screen by default, but out of it).
From a camera perspective, things are always moving and turning the other way. If you move a camera up, it looks like the world is moving down, if you turn it left, it looks the world is spinning to the right, etc. Of course it would be absurd to manually apply that to every single object, but depending on your API/framework, that's what happens automatically. In DX you set the view matrix and the default shader will always multiply it with the objects transformation matrix (ObjectMat * ViewMat).
Well, how would you rotate without a vector (or in this context: axis)? Rotating "left" or "clockwise" without an axis is meaningless. It might seem to make sense to you, because you assume a context where you deal with a standing person or vehicle. The axis you rotate around is the one thing not affected by the rotation (except for your position). If you picture sticking a pencil into your head so that when you turn it always points in the same direction, you will soon realize you're rotating around your "up", aka local y-axis, aka (0,1,0)... (or "down", if you flip the axis and invert the angle it's the exact same thing).
What might help a lot in visualizing things is to grab any 3D modelling software of your choice. Most of them will always display the objects local coordinate system as three color coded arrows sticking out from it. If you get used to thinking of everything in your scene to have these arrows and how each arrow is one column of the transformation matrix, things should become a lot more intuitive. Just think of the camera as one more invisible object and don't worry about the whole "inverse matrix" while modifying or placing it. Treat it as a separate step at the end of everything else.

#5247588 Quaternions for FPS Camera?

Posted by Trienco on 19 August 2015 - 01:20 AM

You seem to be confused about the difference between points and vectors and what's supposed to be what (or your naming is just really misleading). (0,0,0) is NOT a useful vector. It has zero length. It has no real direction. It can't be rotated and nothing can be rotated around it. If it's your camera position, it is the one thing that has no business being involved in any of your rotations, because an objects position is irrelevant and separate from its orientation.


Generally, when people are talking about a "view vector", they mean the direction your camera is pointing at (also typically normalized to be unit length).


With all the 0s in your code, I'd expect either that absolutely nothing happens or that the result is completely unpredictable and undefined (try normalizing a zero length vector).


Your first step should be to get an understanding of what you're trying to do and visualize it.


Step one:

Forget you ever heard the word "quaternion". Seriously, if you're a beginner and still trying to wrap your head around rotations and how to get a grip on the camera, 4-dimensional complex numbers should never ever enter the equation at any point. For your task, they offer zero benefit, are most likely less efficient due to all the conversion between matrices and quats and will just add a pointless extra layer of confusion and complexity. Suggesting quats for a simple FPS camera is like telling someone who struggles with a ray-triangle test "you must haz Plücker coords, them's the only way.. you won't understand the underlying math (I didn't), so just copy/paste some code, then go forth and spread the gospel of the one and only true and almighty Plücker" (yes, that's basically the impression I get with everybody immediately telling people to use quats whenever a topic remotely involves rotations).


They are neat and very useful in some cases, but they should still be considered a specialized tool. You wouldn't use a power drill to get a nail into the wall, just because both jobs involve putting a longish piece of metal into a hole.


Step two:

Understand transformation matrices. They aren't mysterious black boxes that magically make graphics happen. In fact, they are by far the easiest representation to visualize an objects orientation in your head (easier than quats and definitely easier than Euler angles). The three columns are literally nothing but your objects right/up/forward vectors. Creating any orientation that only involves 90° (or even 45°) steps is easy enough to not require a single bit of calculation (not that this would ever be useful in practice, just making a point).


Case in point, rotating 90° to the left means "right" is now pointing "north", "up" is still.. uhm.. "skywards" and "forward" is pointing "east" and your position didn't change (let's assume at the origin), ie. the columns are (0,0,-1,0), (0,1,0,0), (-1,0,0,0), (0,0,0,1). If the fourth coordinate (w) confuses you, don't worry about the math and just pretend w=0 means "direction" and w=1 means "position". There are generally no other values (at least not in places you care about anytime soon).


Step three:

There is no camera. A camera is just a nice concept to help picturing stuff in your mind. When it comes down to the math, you just move everything the opposite way of your imaginary camera. Still, just treat that imaginary camera like any other object in your scene until you set the view matrix as the opposite of it. What is used to apply the opposite of a transformation? The inverse matrix. What's neat about a typical camera matrix? No scaling or shearing, so there's a simple and efficient way to invert it (though for now, just use whatever inverse function your math library is offering).


Step four:

Multiplication order. To not get hopelessly confused or just stubbornly following a "you must always multiply matrices THIS way"-mantra, understand the difference between R*M and M*R. Say R is a rotation around the x-axis (1,0,0). Typically, matrix multiplications are applies right to left. If you used the deprecated OpenGL functions, "rotate" would result in R*M and apply the rotation AFTER all previous transformations (using the local coordinate system, which leads to confusing claims about OpenGL applying transformations in "reverse order" by people insisting on thinking in global terms).


Doing M*R means you apply R before other transformations, back when your objects axes were still identical to the worlds axes. Meaning: it rotates around the global x-axis. R*M on the other hand applies it last, so the x-axis you rotate around is whatever is "right" after all the other transformations. I prefer thinking in local coordinates, because unless you're writing an editor or deal with external forces in your physics simulation, you don't care about what's "north" or "west", you care about what's "forward" and what's "right" from your objects point of view. If you want to strafe to the side, you don't want to do pointless calculations to figure out what "right" is. It's right there in the first column of your objects transformation matrix. You also don't care, you simply apply a translation along (1,0,0) by doing T*M (and not the other way around). Later you will get rid of wasteful matrix multiplications for a simple translation, but understanding first, making it work second and making it efficient once you know what you're doing.



A few simple kinds of "disembodied" cameras:



-Store a position vector

-Store two angles for left/right and up/down

-Limit up/down to values

-Create camera transformation: M = rotateAroundX(up/down) * rotateAroundY(left/right) * translation

-Invert, orthonormalize and set as view matrix (you can do the inversion implicitly like Norman Barrows by inverting all signs and the multiplication order, but the idea is picture what's going on, not to optimize).


Third person:

-Store two angles for left/right and up/down

-Store a distance to the observed object

-Limit up/down to values

-Create camera transformation: M = translateBackwards(distance) * rotateAroundX(up/down) * rotateAroundY(left/right) * translation(position of observed object)

    -"Backwards" depends on your coordinate system. with a right handed system most likely (0,0,1).. I prefer left handed, since positive z being forward is more intuitive

-Invert, orthonormalize and set as view matrix


Free camera (think flight simulator):

-Store the whole matrix as one (4x4)

-Add transformations depending on input each frame (do NOT reset the matrix at any point)

     -Do it in local terms (ie. forward is translation(0,0,-1) * M, pitch (up/down) is rotation(1,0,0, angle) * M, etc.)

     -Order of multiple transformations not relevant within frames. While the results are different, changes between frames should be very small and it won't matter much.

-Orthonormalize, invert and set as view matrix


Note that the "normalize" part comes first in this last case. Accumulating all the transformations will add more and more floating point issues and screw up the matrix over time, so it should be "repaired" from time to time (fix axes to be orthogonal to each other and normalize the them to be unit length... don't touch the last column, which is the translation/position).


Those are not be the most efficient, fancy or flexible methods, but they should involve the least effort and are the most trivial ways to achieve a trivial goal that I can think of. Also, if there is one part of your engine where performance usually doesn't matter, it's the camera that is only set up once every frame anyway.

#5247337 Quaternions for FPS Camera?

Posted by Trienco on 18 August 2015 - 02:55 AM

Typical FPS style cameras are one of the few cases where storing two angles is perfectly fine and sufficient (and quaternions are likely to be pointless overkill that turn something simple and trivial to visualize into completely abstract math). As long as "typical" means "ground based", so usually without rolling and up/down rotations being limited to 90°.


All you need to keep in mind is that every rotation will also affect the axes that are used by all subsequent rotations. So for an FPS style camera, you always apply your "left/right" rotation first. Otherwise, if you do the "up/down" first, your "up-axis" for the second rotation would be screwed up, plus, your first rotation would be around the global "right", rather than your current local one.


The only issue you can run into is that depending on the API you use and the multiplication order in which you apply transformations can have an impact on which transformation happens "first". On top of that, your own perception of what happens first depends on whether you look at your object from a global or local perspective. For example, if you insist that "right" is always the global x-axis, transformations will appear to happen in reverse order, while considering "right" to be the objects own current x-axis will usually mean they happen in the order you apply them in (I also find the latter to be more useful and less confusing than the "global perspective").


A very appropriate definition of computer graphics I remember from some book was something like "computer graphics is the art of making an even number of sign errors".

#5244231 C++ Operator Overloading: Bitwise Operators & If-Check

Posted by Trienco on 02 August 2015 - 09:44 PM


Second, your conditional idiom is slightly problematic even with plain integers, unless you particularly like getting lots of warnings:

if(f & uf) ;//do stuff. should be true with the example-argument above.
if((f & uf) != uf)


Why is the second preferred?


I suspect it was supposed to be (f & uf) != 0, since the other version is definitely not equivalent. It prevents the implicit cast from unsigned to bool and all the potential compiler warnings that come with it (in VS it's usually something about runtime performance).

#5239764 The fruits of laziness

Posted by Trienco on 11 July 2015 - 11:08 AM

Sometimes you just get very tired of writing endless tons of boiler plate code. Case in point, importing/exporting nested data hierarchies. Due to reasons, fields aren't explicitly looked for, since they might have been "inherited" through referenced sub-objects and will only be partially overwritten.


So after staring at endless screens full of if-else-if-else-if string comparisons for each element name, you develop a desire to automate this kind of mess.


Enter the scary depths of boost::fusion and the black magic that can invoked by macros and template meta-programming.


So, this now automagically "just works":


BOOST_FUSION_DEFINE_STRUCT((test), TestStructNested,
    (float, myFloat)
    (unsigned, noSign)
    (MyEnum, greekLetter))
    (bool, yesNo)
    (std::string, someString)
    (test::TestStructNested, nested))
int main()
    test::TestStruct myStruct;
    pugi::xml_document doc;
    fillStructFromXml(doc.first_child(), myStruct);
    pugi::xml_document newDoc;
    addStructToXml(newDoc.append_child("root"), myStruct);
    return 0;



And yet, despite the luxury of being able to add new fields and structs and enums without writing a single line of code to actually read/write them, the real horror is what makes it work and the bad feeling about unleashing it unto mankind.


Having functions to convert enums from/to strings isn't too uncommon, so some people have already been unfortunate enough to see things like this:


    else if (!strcmp(str, BOOST_PP_STRINGIZE(ENUM_VALUE))) v = ENUM::ENUM_VALUE;
    inline const char* toString(const ENUM& value) {\
        switch (value) {\
            default: throw std::runtime_error(std::string("invalid value for " BOOST_PP_STRINGIZE(ENUM) ": ") + std::to_string((unsigned)value));\
    inline void fromString(const char* str, ENUM& v) {\
        if (!str) throw std::runtime_error("String can't be null");\
        else throw std::runtime_error(std::string("invalid " BOOST_PP_STRINGIZE(ENUM) " value: ") + str);\



But the real "beauty" is the code that iterates over the adapted struct members until the member name matches the xml element name and recursively delves into nested structs...


template<class XmlNodeType, class MemberType>
typename std::enable_if<std::is_class<MemberType>::value, void>::type
inline fromElement(const XmlNodeType& node, MemberType& member)
    for (const auto& child : getNodeChildren(node))
        setMemberFromXml(child, member);
template<class XmlNodeType, class MemberType>
typename std::enable_if<std::is_enum<MemberType>::value, void>::type
inline fromElement(const XmlNodeType& node, MemberType& member) {
    fromString(getNodeText(node), member);
template<class XmlNodeType, class ValueType>
typename std::enable_if<std::is_integral<ValueType>::value, void>::type
inline fromElement(const XmlNodeType& node, ValueType& value) {
    value = static_cast<ValueType>(strtol(getNodeText(node), nullptr, 0));
template<class XmlNodeType>
inline void fromElement(const XmlNodeType& node, std::string& value) {
    value = getNodeText(node);
//Bunch of additional overloads
template<class XmlNodeType>
struct SetMemberByName
    SetMemberByName(const XmlNodeType& node) : xmlNode(node) {}
    template<typename Iter, typename End>
    void doIt(const Iter& it, const End& end, boost::mpl::false_)
        const char* memberName = boost::fusion::extension::struct_member_name<Iter::seq_type, Iter::index::value>::call();
        if (!strcmp(getNodeName(xmlNode), memberName))
            fromElement(xmlNode, *it);
        doIt(boost::fusion::next(it), end,
            boost::fusion::result_of::equal_to<typename boost::fusion::result_of::next<Iter>::type, End>());
    template<typename Iter, typename End>
    void doIt(const Iter&, const End&, boost::mpl::true_) {}
    const XmlNodeType& xmlNode;
template<class XmlNodeType, class StructType>
void setMemberFromXml(const XmlNodeType& node, StructType& obj)
    using namespace boost;
        typename fusion::result_of::begin<StructType>::type,
        typename fusion::result_of::end<StructType>::type>());
template<class XmlNodeType, class StructType>
void fillStructFromXml(const XmlNodeType& root, StructType& obj)
    fromElement(root, obj);


I still can't tell if that represents reaching a new level of C++ or entering a new circle of hell. The mere thought of what must be going on in those boost headers is pure nightmare fuel.

#5238909 How to switch turn in a card game?

Posted by Trienco on 07 July 2015 - 09:51 PM

It's always a little worrying when conditional logic is thrown at simple "number problems". While I agree it's easier to understand in "for beginners", it also teaches bad habits (yes, I consider needless branching as bad style).


Plus, in a more generic game with 2-8 players, you'd be completely screwed with any kind of "if it was player x's turn, it is now player y's turn" logic.


List<Player> players;
int activePlayer = 0;
while (playing)
    //do stuff for players[activePlayer]
    //next player, modulo (%) will ensure wrapping back to 0 after the last player
    activePlayer = ++activePlayer % players.Count();


And if you prefer more readable code, keep in mind that pretty much every time you feel the need to comment a piece of code, it should probably be made a function named very much like what your comment is saying:


int nextPlayer()
     activePlayer = ++activePlayer % players.Count();
while (...)
    activePlayer = nextPlayer();

#5238526 Am I doing it all wrong?

Posted by Trienco on 05 July 2015 - 10:04 PM

Programming isn't about memorizing code. It's about understanding your tools and the ability to use them to figure out a solution to a problem. The code isn't "what" you're doing, it's "how" you're doing it. What you generally want to learn is the "what", because the "how" will come naturally if you know your tools.


In practice, you will usually solve each problem once and later go back to reuse or copy from your previous solution. Though it can make sense to force yourself to write it again and again a few times in some cases, until a particularly common algorithm (say quick sort, A*, etc.) isn't just that "mysterious chunk of code I wrote years ago and don't remember how it works". 


Copying from tutorials was probably not the point of writing them. Not only because it can be embarrassing to have code that calls "MyFunc" (yes, I've seen that kind of thing in production code), but because the point of that code is to illustrate and focus on a particular point or technique. That means there's usually little to no error handling and room for optimization, because that would obfuscate and distract from the actual subject matter. Also, unless you plan to build your whole program around a tutorial, it will rarely be something you can just drop into the rest of your code without plenty of adjustments. And then there's always the copyright question and what kind of use is permitted by the tutorial code's license.


So I'd move on to the next project. Learning and experience will happen naturally, unless you plan to wipe your memory or drink yourself silly after each programming session. While doing that, you will probably revisit your last project a lot anyway. For practice, resist the urge to copy/paste, if you just want to get it done, reuse away (just try not to copy comments or names that are nonsensical in the context of the new game).

#5237950 If-else coding style

Posted by Trienco on 01 July 2015 - 10:21 PM

The only reason I can think of why this could be called "misleading" is that at the very first superficial glance you see a function that return something, but only does so inside two blocks. So my very first impression would be "the main code path is missing a return". You'd have to look and check that it's indeed an if-else and not and if-if or other constructs.


That said, for easy constructs I usually go with ?: as well. If expressions are more clunky, I prefer early outs (ie. all error cases) at the top, so they are out of the way of what actually needs to be done without unnecessary nesting.


My personal pet peeve however is


if (condition)
    return true;
   return false;


This weird refusal to just use "return condition" or at least "return condition == true" (if you feel a need to be extra verbose) is somehow mostly seen with C-programmers. Probably still not used to bool being an actual type and basing it on "I tried BOOL func() {return flags & FLAG_X;} once and it failed, so I decided that returning a condition is always wrong in every way".

#5232089 Defning a namespace class in a header file

Posted by Trienco on 31 May 2015 - 10:13 PM

I doubt it even gets to the point of worrying about a constructor. Without knowing the actual size of the class, it doesn't even know how much space the instance will need on the stack. In the same way, if it was a member variable, it couldn't determine the size of the enclosing class.

#5229257 Basic 2D array C problem

Posted by Trienco on 15 May 2015 - 10:38 PM

I've worked with too many people that never managed to completely transfer from C to C++ and still stick to all their bad C-habits. You can often tell which code was written by a former C programmer. Examples (vaguely based supposed _C++_ on code at work):


typedef MyStruct {...} MyStruct_t;
int myFunc(void) { ... if (success) return 0; }
void stringStuff() {  if (str.compare(str2) == 0) {...} }
void func()
    int a;
    int b;
    int c;
    a = 0;
    b = 1;
   if (blah)
       if (moreBlah)
            c = func();
class MyClass
    MyClass() {
        member1 = 0;
        member2 = 0;
        member3 = 0;


So, unless your future career is pure C89, do yourself and any future coworkers a favor: skip C and don't pick up all those habits in the first place.

#5227882 Trying to write my own GUI with SFML

Posted by Trienco on 07 May 2015 - 09:59 PM

Just as a quick example what you can do with a relatively simple approach described by AnnaMarie and me: 


While I wouldn't use the code as example for great coding, the GUI code is relatively well separated (the gui directory has the classes with the logic, the renderer has the functions to draw the elements).



#5227232 Trying to write my own GUI with SFML

Posted by Trienco on 04 May 2015 - 10:12 PM

I usually go with a base class that contains a child container. Child elements are sorted (either top to bottom). To draw elements, I disable the z-test (too annoying to offset each element) and draw bottom to top (you can use the parent element dimensions as viewport to get automatic clipping).


When processing clicks, you go through the children top to bottom, so clicks are automatically processed by the right window and you don't need to care about overlapping. You might also want to have some kind of mechanism that allows "useless" elements to forward clicks to their parent element (a button might contain a label, yet when you click the label you generally want the button to trigger). Again, the easiest way is to avoid special handling and make the default event handler call the parents event handler.


Also, after you figured out which element was clicked on, loop over it and all parents and move them to the front (or back, whichever is "top") of their own parents respective child list.


Getting a basic ("static") GUI to work is usually pretty trivial, up to the point where you add drag & drop (which is unfortunately often the most convenient way to do stuff).

#5220616 c++ Instantiating a class in another class

Posted by Trienco on 01 April 2015 - 01:18 AM



It may not be necessary but it's probably good practice, just like putting return 0, at the end of main.




One is explicitly returning the exit status instead of relying on an implicitly generated default, the other is changing global state after it has any meaning or use and right before it gets destroyed anyway.


So I would rather compare it to setting a member variable to 0 in your destructor.