Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!

1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Member Since 22 Aug 2001
Offline Last Active Today, 09:11 AM

#4933705 Measuring performance - overdraw

Posted by Trienco on 21 April 2012 - 10:53 PM

And finally, one more thing that bothers me most. In the very first scenario I described in this thread, with the plane mesh filling the whole screen and taking 190ns to render, I noticed that depending on how close the camera was to the plane, the render time varied, despite the fact that the plane was the only geometry entity filling the whole screen. I noticed that the closer the camera was to the plane, the less time it took to render it. My times varied from 180ns (as close to the plane as possible without frustum near plane clipping) to 220 ns (as far as possible to still fit the entire plane on the screen).

Why is that a surprise? You sound like you somehow moved from thinking that only the number of polygons matters to thinking that only the number of pixels matters. You get closer to the plane, more geometry gets clipped, fewer triangles get rasterized -> less overhead. You are measuring ns. There are about a gazillion factors that come into play, many of them hidden from you by things the driver might be doing or just the way stuff happens in the hardware.

How are you even measuring the exact timing for vertex and pixel processing when these things should be processed in a pipeline on the hardware? If you have more than one triangle, it's not first going to process all vertices and then do all the pixels. One triangle is done and gets rasterized/shaded while at the same time the next triangle gets prepared. There are caches, the second time around a vertex might not even be processed anymore. Hardware today has unified shaders that can be dynamically used for either vertex or pixel processing, completely changing how long vertex and pixel processing will take.

There is little to no point to make ns measurements and expect any obvious and linear relationship between numbers. Not on modern hardware.

#4932367 Are Pack Files (PAK, ZIP, WAD, etc) Worth It?

Posted by Trienco on 17 April 2012 - 10:26 PM

I feel the need to add a good example of the media understanding enough about to screw you over.

Over here, we pay a small fee on every blank medium (from printer paper to DVDs) than can be used to copy stuff. At a time they even tried introducing it for RAM, arguing that there are "temporary copies" created in RAM. In return we have the right to create "private copies" and distribute small numbers to friends (rule of thumb says around 7 and you must be familiar with the people you give them to).

Then the lobbying began to change copyright laws and just as Hodgman said, it was now illegal to copy anything with a copy protection (there was a wording about "effective copy protection" which I bet has been removed by now, because obviously if you can copy it anyway, it wasn't that "effective"). As a result, everything is copy protected, we still pay that fee for everything, but the "private copy" thing has become purely hypothetical.

In short: don't underestimate the amount of legal stuff companies and lawyers can throw at things. Even if they don't have a clue about the technology they will still try to drown in licenses, just to legally be on the safe side. Particularly if you use licensed art, expect them to enforce some way make it non-trivial to just extract and distribute it.

#4932015 Help fix pong enemy paddle please?

Posted by Trienco on 16 April 2012 - 09:47 PM

Of course it is. Put a breakpoint in there when it does that and you might notice that the ball is above the paddle, then the paddle moves and is above the ball, so the next frame it will move down again and on and on and on.

A concept you might want to look up is called Hysteresis (IF you really want to keep that approach).

Even if you add an area where the paddle doesn't move it won't look very natural to constantly stop-move-stop, because a real player estimates where the ball WILL be when it reaches him. AI can easily calculate that, add a random error and simply move to that position. To look more like a human player, the calculated position can be adjusted every once in a while as the ball gets closer and the random error gets smaller.

#4931628 I include a .h and my project expodes with errors :(

Posted by Trienco on 15 April 2012 - 10:23 PM

Maybe it's just me, but I would really get into the habit of NOT using #include in header files except when you really need them. Using forward declarations wherever possible means not ending up with including includes that include includes that end up with every single source file including almost every header in your entire project.

If your class is only showing up as a pointer or reference in some other header, do NOT include the entire class header and just forward declare. After a while it will be as natural as not putting 'using namespace' in header files and just type out the entire names.

#4931348 Beginning c++ through game programming third edition, solutions to exercise a...

Posted by Trienco on 14 April 2012 - 10:57 PM

There is no point in creating a variable for every single enum value (and get into the habit of declaring them const, when they aren't supposed to change)

The location of declaring choice is plain weird, declare them right before they are used for the first time and in their own line (and initialize... always). What if you fail to read because the user entered "slkjsfg"? Choice will still have some random value.

Don't use if/else chains when a switch is perfectly fine.

Put success _inside_ the loop, inizialize to true and avoid setting it in every single if block (removing the need to do something in a million places removes the possibility to forget it half the time).

#4931137 Importance of structs?

Posted by Trienco on 14 April 2012 - 01:58 AM

While technically there is no real difference, you might sometimes find code where structs are used for plain data and classes are used when it also contains functions to operate on that data. So if you do want to make a difference, make it the distinction between data vs. behavior. Or in other words, if your thingy is supposed to "do" something, call it a class, if it's merely a dumb container for data, call it struct.

#4931116 Importance of structs?

Posted by Trienco on 13 April 2012 - 10:45 PM

You put data in structs. Especially if you need that data "as a whole". Imagine you have a bunch of things that can have an address (persons, shops, ...). You do NOT want to spam street/zip code/city/country as separate members into every single one of them. Most likely you will have functions that operate on addresses (printing them on labels, doing a sanity check). And again you wouldn't want each of these functions to take each value as a separate parameter. Even more so you may have a function that should create and RETURN an address. Functions simply can't return more than a single thing (unless you go with ugly workarounds like having half a dozen output parameters, which are an ugly concept that should be avoided whenever possible).

In short: whenever something belongs together (and will be used more than once), put it in a struct.

I guess this needs some example to demonstrate how utterly messy and unmanagable things would be without structs.

Start simple, you want to manage people. Let's say they have a name, age and gender. Let's also use a simple array instead of lists to store them. Also, have a function that can print a persion.

Without structs
string name[50];
int age[50];
int gender[50];

void printPerson(string name, int age, int gender)
   cout << name << age << gender;

or even some really bad style, that requires all your above arrays to be (semi)-global
void printPerson(int index)
   cout << name[index] << age[index] << gender[index];

With structs:
struct Person
   string name;
   int age;
   int gender;

Person people[50];

//I deliberately ignore the option to pass by reference
void printPerson(Person someone)
    cout << someone.name << someone.age << someone.gender;

//There is now no good reason to pass an index to the function.

Let's say you need a function to create a person or read one from a file

Without struct
void readPerson(File file, string* name, int* age, int* gender)
    *name = ...;
    *age = ...;
    *gender = ...;

using it would require this:

string name;
int age;
int gender;

readPerson(file, &name, &age, &gender);

If you had a struct, it could be easier

Person readPerson(File file)
    Person person;
    person.name = ...;
    person.age = ...;
    person.gender = ...;

    return person;

and using it would just be

Person person = readPerson(file);

Now let's add Addresses and Shops without using a struct for the address.

struct Person
   string name;
   string street;
   string zip;
   string city;

//Yes, this is easy to write AT FIRST by just copy/pasting stuff... and you will hate yourself for every single Ctrl+V when you need to add the country to the address EVERYWHERE

struct Shop
   Person owner;
   string name;
   string street;
   string zip;
   string city;

compare that to
struct Person
   string name;
   Address address;

struct Shop
   Person owner;
   string name;
   Address address;

In short, structs let you structure your code and avoid redundancy,usually resulting in lots of copy/paste. If you find yourself copy/pasting whole blocks of code, stop it and ask yourself why you even NEED to do that in the first place.

Structured code means less work, easy to maintain, extend and use. Also a lot less bugs, which is what happens when code becomes a huge mess where it gets increasingly hard to figure out what is happening when, where and how.

#4928117 how to force global variable which define in a static library to initialize?

Posted by Trienco on 04 April 2012 - 12:05 AM

One of my "favorite" issues that caused a lot of pain.

With VC++ you usually get away with actually referencing the variable somewhere (a dummy read in a destructor or whatever). GCC will actually delay it until the very first time the variable is actually accessed. So you can not rely on any side effects caused by the initialization to actually happen before main.

In short, trying something like this will usually not work:
bool classXisRegistered = registerClassX();

For VC++, you might get away with a simple reference somewhere
	bool dummy = classXisRegistered;

For GCC we actually had to create static global objects that would have the desired side effect in the constructor. And based on all the weird rules about how a compiler may optimize, I wouldn't rely on even this to work for absolutely every compiler.

class Registrator
   Registrator() { registerClass(); }

static const Registrator registerClassX;

By the way, this method still failed on another project, where this code was in a static lib that was used to build a dll. Somewhere along the way the linker still decided to drop it. They moved the entire code to be a direct part of the dll.

I played around and tested a few methods, which ended up in a somewhat convoluted test:

But I guess the easiest solution is to simply not rely on any side effects of global static variable initialization.

#4927498 Newbie here, I wish to start.

Posted by Trienco on 02 April 2012 - 08:03 AM

Though it would technically be possible to create a "turn based" Pong on the console with nothing but the standard library.

Text-based Pong ftw!
>>> you move your bat:
>>> 4
>>> units
>>> you miss the ball!
>>> **** YOU LOSE ****

Well, I was thinking more along the lines of an o for the ball and a couple |s for the bats. The reason I said "turn based" is because I don't know any non-standard way in C or C++ to get keyboard input without blocking.

TL;DR: try and be more open-minded. Nobody's forcing you to anything but it doesn't hurt to look beyond what one already knows and actually try it out long enough to get comfortable with it - who knows, you may actually like it!

To emphasize this point: I had co-workers with up to 40 years of experience in C that unfortunately spent at least 30 of them stubbornly refusing to learn anything new. Their code tended to be messy, not because you can't write clean code in C (you can), but because all the extra work resulted in taking shortcuts and just be sloppy to finish in time. So you had code with plenty of bugs that were also a pain to find in all that mess.

Of course I might simply be biased because I spent many years being the guy that had to find and fix bugs in other peoples code whenever the bug reports came in.

Nobody expects anyone to instantly transition to C++ and write what is so nicely called "modern C++". But flat out refusing even the option to make use of some extremely useful and time saving features out of a feeling of being "overwhelmed" by all the new possibilites? Really?

#4927376 Newbie here, I wish to start.

Posted by Trienco on 01 April 2012 - 11:22 PM

Because I find C++ too cluttered with all the OOP stuff,iterators, dynamic/static casts(with weird declarations, too),templates,maps, the list goes on. Whereas C is much easier, and typecasting is done via (type)variable and voila.

So in other words "I'd rather use a tooth pick for construction work than learning how to use those overrated 'power tools' everybody is talking about".

How is C "easier" if you end up wasting 80% of your time reinventing countless wheels instead of actually making progress with the game?

Based on your choice of language and current level of knowledge the only advice that comes to mind is: if you aim higher than a very simple Pong clone as a first project, you are over reaching. And even that means getting familiar with at least one way to get graphics on the screen (meaning a library) and reading keyboard input beyond scanf. Though it would technically be possible to create a "turn based" Pong on the console with nothing but the standard library.

#4927117 Forward declaration and a singleton class

Posted by Trienco on 01 April 2012 - 01:54 AM

Note the first line, you need to forward declaring there.

That's useless. A forward declaration simply says "a class of that name exists somewhere". It will NOT actually let you use that class, because the class is still undefined and it is completely unknown what is IN that class.

A forward declaration let's you do pretty much nothing but pass around pointers/references to that class. You still can't declare a variable of that type (because the size is unknown) and you can't call any functions of it (because they don't exist without actually DEFINING the class and what it looks like).

The simple matter of fact is that you can't "use" a forward declared class.

Fixing dependencies like that is usually based on NOT dumping your implementation in the header file, though in this case as SiCrane already said: DEFINE the class, before you try to use it.

#4926875 Smart pointers question

Posted by Trienco on 30 March 2012 - 11:32 PM

Basically have a single look-up table to see if the item is not deleted everytime you use it, like overriding the '->' operator. That way the ObjectFactory could still track the Gameobjects.

I see a tiny flaw in your concept. What is -> supposed to do if the object WAS deleted? Return 0, automatically have it dereferenced and crash? Or "secretly" redirect your call to a "null object" that simply does nothing?

I see only three scenarios.

a) You say "as long as anybody is still using that object, I must not delete it" -> use shared_ptr... you can still always remove it from whoever manages it, but you delay destruction until the user is done with it

b) You say "it is safe to assume by the time I clean up my table, nobody should be using that pointer anymore". In that case, use raw pointers or unique_ptr/auto_ptr (to clean up automatically when you remove the table)

c) You argue that "the user code should always make sure the pointer is still valid before using it". Use a single shared_ptr for the table and deal out weak_ptr to whoever uses it.

Or wrap it up in a way that returns a null object, if you really and absolutely don't want users to check the pointer. IF you can say "I don't care about nothing happening in that case. It still beats having to check the pointer every single time".

However, in a multi threaded situation (where objects might be used in more than one thread) I would always go with shared_ptr. Simply checking before use is worthless, when the object could be destroyed right between checking and using.

#4925523 Moving to a Point on a Circle

Posted by Trienco on 26 March 2012 - 10:13 PM

Uhm... maybe I'm missing something, but what exactly would be wrong with not putting up with any angles at all? There seems to be an unhealthy obsession with trigonometry where nobody needs it. (Also, all those confusing if's make my head hurt.. math for the most part doesn't generally doesn't work that way).

Look at what you're doing. You already KNOW the vector and instead of simply scaling it to the right length, you bash the problem with the trig club to calculate angles you then use to calculate a shorter version of that same vector. That is simply overcomplicating the problem with a pointless detour.

const Vector3 directionToCam = (Cam - Selected).normalize();
return Selected + (directionToCam * MaxDistance);

//If you really want to be on a circle (not a sphere):
//However keep in mind that if you move it to that position, you will no longer be centered on the object.

Vector3 directionToCam(Cam.x - Selected.x, 0, Cam.z - Selected.z);
Vector3 Calculated = Selected + (directionToCam.normalize() * MaxDistance);
Calculated.y = Cam.y;
return Calculated;

#4924911 OpenGL DrawArrays acting strangely

Posted by Trienco on 24 March 2012 - 10:27 AM

A (x or y) coordinate isn't a vertex and a quad only has 4 vertices. Why are you passing 8?

#4922175 Calculating CPU usage

Posted by Trienco on 14 March 2012 - 11:25 PM

I don't get it. Maybe my world view of how programs are executed is outdated on modern machines. Process is allowed to be executed by scheduler, process runs at CPU clock speed. They don't run faster or slower because "they use a lot of CPU". IPS also seems like a pointless concept. A div takes more cycles than an add. Does that mean a program using lots of divs executing for the same amount of time is using up less CPU, because you get much lower IPS?

You could use a clock that allows measuring actual process or even thread time (not sure what the equivalent is for Windows). A normal timer would not just tell you "this code was giving up its time slice more often or spent more time in blocking operations" it will also tell you "there might have been more higher priority processes active at the time or the scheduler simply had a bad day".

In the same way, stopping how long your code is executing only works for small parts of code and with multiple test runs (or by using a clock that only counts actual time spent in this thread). By just stopping the total time, you would also measure all the time spent in totally different processes whenever the scheduler interrupts you. As an alternative, you could set your thread to realtime priority, but you better make very sure you have a way of ending it and don't get stuck in some loop (or it's reset time).