November 2009 Archives

New job!

| No Comments
Tomorrow monday is officially my first day working for RandomControl as the fryrender plugins subsystem developer and maintainer.

By the way, I'll be telecommuting from home, so I'll avoid cubicle-work once again (yay!)

And, well, I hope this job leaves me some time (and it doesn't eliminate my coding-mood) so I can keep on posting some weird stuff here!

And now, I'm going to bed. Gotta get up early to go to the office tomorrow in the morning :-P

Voronoi video-filling

| No Comments
After showing the last test to a colleague, he guessed that this method would look really bad if seen in motion, using a random sampling method for the image. He thought that a constant sampling pattern would be needed... and so I had to test it out.

This is the result, using a video sample from a Fringe episode. I think it's not half-bad when you get past 1000-2000 samples in the image. And it's completely real-time! :-)

Voronoi image-filling

| No Comments
Little test to see what can you do to approximate a big image using only a few samples, and using Voronoi diagrams for that. It's not amazingly cool or anything, but it runs in real-time :)

C++ template instantiation problem (and some solutions)

| No Comments

Disclaimer: Really long post. If you're not interested in C++ templates (or in correcting me when I write about them), don't read this! Also, if you know more about C++ than I do, please respond with a better solution!

Now, these days I've been reading one of Herb Sutter's wonderful books (Exceptional C++ Style), and one advice he gives is "Where possible, prefer writing functions as nonmembers nonfriends". His arguments seemed pretty solid, so I decided to give it a shot. However, not a day after reading that, I've already found something that keeps me from doing it in certain types of templated code.

For the small engine I've been writing, I've coded a templated Vec2<T> class. And writing some code to test it, g++ gave this wonderful error:

error: no match for 'operator*' in 'geom::Vec2<float>(((const float&)((const float*)(&-1.0e+1f))), ((const float&)((const float*)(&0.0f)))) * ((#'float_expr' not supported by dump_expr#<expression error> * 5.00000000000000010408340855860842566471546888351e-3) + 1.0e+0)'

The line that gave that error is this one:

geom::Vec2<float> v = geom::Vec2<float>(-10,0) * (1+rand()%10*0.005);

The problem (leaving aside some really weird things about float_expr and dump_expr) seems to be that the compiler can't find operator*, even though I did write one. So, what's happening?

Let's see. operator* is defined as a nonmember method, like this:

template <typename T> const Vec2<T> operator*(const Vec2<T> &lhs, T rhs) 
    return Vec2<T>(lhs.x*rhs,lhs.y*rhs); 
}

And if we look close at the line where it fails, we see it's a multiplication just like    

Vec2<float>(10,0) * 0.005

See the problem now?

The compiler, at the moment of the operator* template instantiation, has to choose the type of the template to instantiate, but finds none that fits exactly. It finds that it should call operator*(Vec2<float>, double), but there's only operator*(Vec2<T>,T) defined, so it just sighs and proclaims "What the hell do you want me to do with this?".

In fact, what we probably want it to do is to convert that double to a float, and then choose the float version of operator*. However, the compiler is not smart enough to do that. As it happens, templated functions parameter type selection and automatic type conversion don't usually mix very well (I read something about it from one of Sutter's books, but I don't remember the exact details). So what can we do? 


Option 1 (bad)

One option would be to give the compiler a little nudge (well, not so little really) so it chooses the correct template instantiation. For example, this would compile cleanly:

geom::Vec2<float> v = geom::Vec2<float>(-10,0) * (float)(1+rand()%10*0.005);

However, it's not very polite of us, as utility class programmers, to negate the class user the option to multiply a float vector by a double scalar. So what other option is there? 


Option 2 (better?)

Another option would be to make the operator* method to be a template with 2 typenames, one for each side of the operation. Like this:

template <typename T,typename Y> 
const Vec2<T> operator*(const Vec2<T> &lhs, Y rhs)
{
    return Vec2<T>(lhs.x*rhs,lhs.y*rhs);
}

This would work pretty well. 

As a side note, we would have problems if we tried to do multiplications with the scalar in the left side, like: 

Vec2<float> v = 2.0 * Vec2<float>(10,0);

So we would have to define the swapped version too:

template <typename T,typename Y> 
const Vec2<T> operator*(Y lhs, const Vec2<T> &rhs)
{
    return Vec2<T>(rhs.x*lhs,rhs.y*lhs);
}

The problem with this approach is that every different type we use will instantiate another version of the code. For this particular method it won't really matter because the compiler will probably inline it anyway. But for more complicated methods it will just instantiate another full version of the method, creating a serious case of template bloat. For example (assuming they are not inlined), each of these expressions would instantiate another version of operator*:

Vec2<float> v1 = Vec2<float>(10,0) * 65; 
Vec2<float> v2 = Vec2<float>(10,0) * 65.0; 
Vec2<float> v3 = Vec2<float>(10,0) * 65.0f; 
Vec2<float> v4 = Vec2<float>(10,0) * 'a';


In fact, if we compile those lines with the -ggdb flag, and then inspect them with gdb, we'll see all the instantiations appear:

(gdb) info function geom::operator*

All functions matching regular expression "geom::operator":

File test.cpp:

const geom::Vec2<float> geom::Vec2<float> const geom::operator*<float, char>(geom::Vec2<float> const&, char);

const geom::Vec2<float> geom::Vec2<float> const geom::operator*<float, double>(geom::Vec2<float> const&, double);

const geom::Vec2<float> geom::Vec2<float> const geom::operator*<float, float>(geom::Vec2<float> const&, float);

const geom::Vec2<float> geom::Vec2<float> const geom::operator*<float, int>(geom::Vec2<float> const&, int);


I know this is an exaggerated example, but template bloat (excessive template instantiation) can be a real problem. So, in the end, I'm not sure this option is a very good idea.


Option 3 (almost good?)

Another option (even though we wanted to avoid it from the start to follow the advice of Mr Sutter) is a member method. As simple as this:

template <typename T> struct Vec2
{
    ...
    Vec2<T> operator*(T scalar) const
    {
        return Vec2<T>(x*scalar,y*scalar);
    }
};

This method would have no problem instantiating, as there's only one possible T it can accept, and it's clear that we want to convert the type of scalar to that type T. And for the same reason, it would only instantiate once (again, assuming the compiler won't inline it because of size or something).

But we would still have the problem with the swapped version. If we try to do a multiplication like 2.0*Vec2<float>(10,0), we'll get a nice compiler error. What can we do about that?

The best way I've found is to do this:

template <typename T, typename Y> 
const Vec2<T> operator*(Y lhs, const Vec2<T> &rhs)
{
    return rhs*lhs;
}

That is, create a nonmember double-typenamed swapped version, and make it just call the member straight one. Hopefully the compiler will inline it (it's a small method after all) and we'll avoid the associated template bloat I talked about previously.

So, in the straight version we've got no template bloat, and in the swapped one we will most likely avoid it too, thanks to the compiler inlining capabilities. We would, however, be forced to use member methods and ignore Sutter's advice this time.


And I've already run out of ideas to get this to work properly. If anyone knows of a more elegant way to do it, or has found an error in code, logic, technique, grammar or whatever, please leave a comment :-)


Time for some OpenGL bashing

| No Comments

Yes, I know, I'm a bit late to the game, but today (after 8 years of using OpenGL exclusively) I've just gotten the small rendering engine I'm working on to use DirectX 9. 

Why DX9 and not 10 (or 11)? Because I need it to run on computers with WinXP (could Microsoft have been more stupid, limiting DirectX like that?)

Anyway, the engine was working on MacOS and Linux, but I needed to be sure to support DX as well (OpenGL drivers for Windows are known to be buggy as hell and fairly incomplete in some cases). So here we are, coding using a propietary Microsoft library. Yes, I know I'm unclean and un-free, but such is life (and for what it's worth, I'm still using bash, g++ and vim, even on Windows ;)

The thing is, after using DirectX for 2 days, I wish OpenGL was more like it in some ways. 

Small example. First, OpenGL code to render from a vertex buffer object:

glBindBuffer(GL_ARRAY_BUFFER, mdataBuffer);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY); 
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexData), (char*)NULL+sizeof(uint8t)*3);
glVertexPointer(3, GL_FLOAT, sizeof(VertexData), 0);
glDrawArrays(GL_TRIANGLES, startVertex, endVertex-startVertex);

And now, equivalent DirectX9 code:

md3dDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE);
md3dDevice->SetStreamSource( 0, mdataBuffer, 0, sizeof(VertexData) );
md3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, startVertex, (endVertex-startVertex)/3);

Those 2 blocks of code do exactly the same thing: take information from a buffer about a bunch of vertices (vertex position and color), and use that info to render some triangles. Just that.
 
But see the difference in the code? Now choose the cleaner, saner API. I don't think many will choose OpenGL. And that's a shame.

Sometimes I hope for a clean API redesign for OpenGL, and do away with all that crap. ...sigh...

I highly recomend this session (page 194) (btw, thanks to shash for that link) where an NVidia engineer talks about problems the OpenGL API (and DirectX's too) causes for application portability. 

New blog, and new video

| 8 Comments
Hi there! New blog (again), I hope this one lives for more than 2 years... 

This last year I got really tired of Drupal, and decided to use something else and create another blog. In the end (after some googling), I decided to go with Movable Type. It's much more organized and stable than Drupal, and has almost no cpu cost for each page view (pages are generated just once as an html, instead of each time a user views the page, like Drupal does). I hope it doesn't give me as many headaches as the old web did...

Also, I've decided to write in english from now on. Almost everyone that read the previous blog knows english, so I won't be losing lots of readers (except my mother. Sorry, mom). And more importantly, this way I get to practice my written english, which has always been my weakest and was weakening by the moment.

And about the page itself, I'm not entirely convinced of the page design (it's just a default theme with a changed header), but it'll have to do for the moment. My design skills aren't really the best, and my designer friends are all too busy to work for free (or in exchange of a couple of beers).

Anyway, to start filling this new web with something useful, I've uploaded a new video showing the output of my software raytracer (anyone remembers?). It's just that I recently upgraded to a quad core machine, and had to test the machine with a heavily multithreaded program :)

So, here's the video (it's in full HD, so hit the fullscreen button!):



The video is also linked in the Software Raytracer page in the Projects section, by the way ;-)