NBA 2K12 is…
r3dux | January 24, 2012
Not even rigged - try it for yourself...
Game is teeth-gnashingly hard against the AI on standard “Pro” difficulty. It’s upsetting.

Not even rigged - try it for yourself...
Game is teeth-gnashingly hard against the AI on standard “Pro” difficulty. It’s upsetting.
I’d never even heard of Hangs / Hang drums before today – check them out! Amazing!
Like playing a flying saucer – really, really well! =D
I’m working my way through the first few chapters of James Reinders’ Intel Threading Building Blocks book, and its a little bit hard going. As much as I’m enjoying the mental exercise of thinking in parallel, when it actually comes to the coding they use a lot of function operator (i.e. operator()) overloading, and I’m not so familiar with it. As much as I’ve overloaded operators before so you could, for example, add two Fruit objects together and get their weight, or multiply an Employee->monthlySalary by 12 to get their yearly wage, I’d never overloaded the function operator itself, so wasn’t sure what was really going on in the code.
To fix this, I’ve knocked together a super-simple example to show how it works:
#include <iostream> using std::cout; using std::endl; class Foo { public: // Property int number; // Constructor Foo() : number(0) { cout << "Constructing an object of type Foo..." << endl; } // First overloaded function operator, i.e. we're overloading the operator () void operator()() { cout << "From our first overloaded () operator, I get the number: " << number << endl; } // Second overloaded function operator void operator()(Foo &first, Foo &second) { if (first.number > second.number) { cout << "The first number property is greater than the second number property." << endl; } else { cout << "The first number property is less than or equal to the second number property." << endl; } } }; void doNothing(Foo tempFoo) { cout << "I'm not using the overloaded () operator here." << endl; } int main() { // Create our first test object Foo firstObject; // Make sure it's initialised with the default value specified in the constructor cout << "From main, number is: " << firstObject.number << endl; // Call the doNothing function on our Foo object - doesn't do a lot! doNothing(firstObject); // Anonymous object creation (i.e. invokes the constructor - but we don't keep a named object) Foo(); // ***THIS*** is where the overloaded function operator comes in! firstObject(); // Create a second test object and specify a value Foo secondObject; secondObject.number = 5; // Run our first overloaded function operator again on a different object secondObject(); // Run our second overloaded function operator on the first object firstObject(firstObject, secondObject); // Run our second overloaded () operator (function operator) again, but on diff object // It doesn't matter which object we run it on - behviour is only dependant on the order // in which we supply the object parameters in this case! secondObject(firstObject, secondObject); // Finally, just to prove we can trigger the second path in the 2nd overloaded function operator... secondObject(secondObject, firstObject); return 0; }
Which gives the output:
Constructing an object of type Foo... From main, number is: 0 I'm not using the overloaded () operator here. Constructing an object of type Foo... From overloaded () operator, I got the number: 0 Constructing an object of type Foo... From overloaded () operator, I got the number: 5 The first number property is less than or equal to the second number property. The first number property is less than or equal to the second number property. The first number property is greater than the second number property.
So, that’s how it works. Straight forward enough.
Another example, taken from the Function object wikipedia page:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <iostream> #include <iterator> #include <algorithm> class countfrom { private: int &count; public: countfrom(int &n) : count(n) {} int operator()() { return count++; } }; int main() { int state(10); std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 11, countfrom(state)); return 0; } |
Counting from 10 to 20 has never been funner =D
Another beautiful song by David Bazan / Pedro the Lion, this time from their 2002 album Control (which has a story, no less).

Audio clip: Adobe Flash Player (version 9 or above) is required to play this audio clip. Download the latest version here. You also need to have JavaScript enabled in your browser.
Fair play to the guy, he can definitely write a catchy tune.
I’m working on using OpenCV to get Kinect sensor data via OpenNI, and needed a way to get a matrix (cv::Mat) into an OpenGL texture – so I wrote a function to do just that – woo! Apologies in advance for the terrible juggling
The function used to perform the sensor data to texture conversion is:
// Function turn a cv::Mat into a texture, and return the texture ID as a GLuint for use GLuint matToTexture(cv::Mat &mat, GLenum minFilter, GLenum magFilter, GLenum wrapFilter) { // Generate a number for our textureID's unique handle GLuint textureID; glGenTextures(1, &textureID); // Bind to our texture handle glBindTexture(GL_TEXTURE_2D, textureID); // Catch silly-mistake texture interpolation method for magnification if (magFilter == GL_LINEAR_MIPMAP_LINEAR || magFilter == GL_LINEAR_MIPMAP_NEAREST || magFilter == GL_NEAREST_MIPMAP_LINEAR || magFilter == GL_NEAREST_MIPMAP_NEAREST) { cout < < "You can't use MIPMAPs for magnification - setting filter to GL_LINEAR" << endl; magFilter = GL_LINEAR; } // Set texture interpolation methods for minification and magnification glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); // Set texture clamping method glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapFilter); // Set incoming texture format to: // GL_BGR for CV_CAP_OPENNI_BGR_IMAGE, // GL_LUMINANCE for CV_CAP_OPENNI_DISPARITY_MAP, // Work out other mappings as required ( there's a list in comments in main() ) GLenum inputColourFormat = GL_BGR; if (mat.channels() == 1) { inputColourFormat = GL_LUMINANCE; } // Create the texture glTexImage2D(GL_TEXTURE_2D, // Type of texture 0, // Pyramid level (for mip-mapping) - 0 is the top level GL_RGB, // Internal colour format to convert to mat.cols, // Image width i.e. 640 for Kinect in standard mode mat.rows, // Image height i.e. 480 for Kinect in standard mode 0, // Border width in pixels (can either be 1 or 0) inputColourFormat, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.) GL_UNSIGNED_BYTE, // Image data type mat.ptr()); // The actual image data itself // If we're using mipmaps then generate them. Note: This requires OpenGL 3.0 or higher if (minFilter == GL_LINEAR_MIPMAP_LINEAR || minFilter == GL_LINEAR_MIPMAP_NEAREST || minFilter == GL_NEAREST_MIPMAP_LINEAR || minFilter == GL_NEAREST_MIPMAP_NEAREST) { glGenerateMipmap(GL_TEXTURE_2D); } return textureID; }
You can then use the above function like this:
// Create our capture object cv::VideoCapture capture( CV_CAP_OPENNI ); // Check that we have actually opened a connection to the sensor if( !capture.isOpened() ) { cout < < "Cannot open capture object." << endl; exit(-1); } // Create our cv::Mat object cv::Mat camFrame; // *** loop *** // Grab the device capture.grab(); // Retrieve desired sensor data (in this case the standard camera image) capture.retrieve(camFrame, CV_CAP_OPENNI_BGR_IMAGE); // Convert to texture GLuint tex = matToTexture(camFrame, GL_NEAREST, GL_NEAREST, GL_CLAMP); // Bind texture glBindTexture(GL_TEXTURE_2D, tex); // Do whatever you want with the texture here... // Free the texture memory glDeleteTextures(1, &tex); // *** End of loop *** // Release the device capture.release();
There's one very important issue to watch out for when using OpenCV and OpenNI together which I've commented in the code, but I'll place here as well as it can be a real deal breaker:
There appears to be a threading issue with the OpenCV grab() function where if you try to grab the device before it's ready to provide the next frame it takes up to 2 seconds to provide the frame, which it might do for a little while before crashing the XnSensorServer process & then you can't get any more frames without restarting the application. This results in horrible, stuttery framerates and garbled sensor data.
I've found that this can be worked around by playing an mp3 in the background. No, really. I'm guessing the threading of the mp3 player introduces some kind of latency which prevents the grab() function being called too soon. Try it if you don't believe me!
So just be aware that if you're using a Kinect you have to be careful with the grab() function... The source code used to create the above video is provided in full after the jump, if you're interested.
Cheers!