Rosario 3D

My developer blog

Let's do optimization

A lot of programmer start with the idea of optimizing everything, they want to save the last clock cycle to make their program faster even if this cost some readability of the code. Making optimized code make you feel smart and sometime you can say… “WOW!! These are the smartest five line of code I ever wrote”

Read more of this post

Vector class

Difficulty: medium (a lot of template)

I want to write an article to speak  about quaternion and how beautiful they are to implement orientation and  keyframe interpolation. But before speaking about quaternion is better to start from the base and create a class for vector.

Vector class

When I speak about vector I refer to maths vector, not an array.  We will develop general version of a vector class that can be used to record our geometry data or other multidimensional data.
This implementation is inspired by the nVidia vector class that you can find with the nVidia SDK, is one of the best Vector class implementation I found. Let’s try to make it better.

Requirement:

  1. Speed: Vector class should be very fast, in a 3d program we will use a lot of vector maths and the speed of this class is crucial for the whole program.
  2. Small size: I also want my class to be compact, I will use the vector class to store the vertex attribute, I don’t want any other data in the middle.
  3. Readability: I want to access to the y coordinate with the .y notation

For the first two reason it’s not wise to use virtual function in our vector class. Virtual function are (slightly) slower, but the most important is that using virtual function will insert an hidden pointer that will increase the size considerably.

Let’s start with the first part of the class, first of all I’ll not create a class but a struct, cause I want all my data to be public, yep I can make the data private and then use getX, getY, setX, setY… but why? This will make only code less readable. A vector is a very simple data that don’t have anything to hide.

template<typename T>
struct Vec4Container
{
   static unsigned const len = 4;
   union{
      struct { T x, y, z, w; };
      struct { T r, g, b, a; };
      struct { T s, t, u, v; };
      T data_[len];
   };
};

I let you immagine how the Vec3Container and Vec2Container is be made.
I have used a template so my class is type independent, now I can create a vector of float, int and so on. I have used union, so I can access to my value with the .x .y .z notation or if my vec represent a color I can use .r .g .b .a or stuv for texture coordinate. OpenGL use s, t, r, q but we already used r in rgb.

Here the real vector class, the one that will perform the computation

template<class container, class T>
struct Vec : public container
{
public:
  static size_t size() { return container::len; }
  Vec() { }
  explicit Vec(const T *v) { for(size_t i = 0; i < size(); i++) container::data_[i]=v[i]; }
  explicit Vec(const T &v) { for(size_t i = 0; i < size(); i++) container::data_[i]=v; }
  Vec(const Vec &vv) { for(size_t i = 0; i < size(); i++) container::data_[i]=vv.data_[i]; }
...

This struct derive from container, so we can access the same data. I also added some constructor,  the first one is the default constructor, I don’t want to initialize my vector if I don’t explicitly needed, then I have a constructor from an array, a constructor from a value. Notice that I have added the explicit keyword, cause I don’t want that a single number can be interpreted as a Vec, this can lead to strange behaviors and confusion. I have added a size operator that return the length of the vector, useful for cycles. Note that this struct don’t add any overhead. The only problem is that cause we are using template C++ don’t know where data_ came from, and we must specify it every time.

We need one more constructor, is very useful to specify a vector like this b(4, 3) or w(1, 3, 5), we need some other classes

template<class T>
struct Vec3 : public Vec<Vec3Container<T> >
{
   Vec3() {};
   explicit Vec3(const T &v) : Vec<Vec3Container<T>, T>(v){ }
   explicit Vec3(const T *v) : Vec<Vec3Container<T>, T>(v){ }
   Vec3(const T& v0, const T& v1, const T& v2){
      Vec<Vec3Container<T>, T>::x = v0;
      Vec<Vec3Container<T>, T>::y = v1;
      Vec<Vec3Container<T>, T>::z = v2;
   }
};

this class will declare only the constructors. The Vec2 and Vec4 are very similar.

Now we can define some basic operation for Vec:

...
   T& operator[] (int i){
      return container::data_[i];
   }
   const T& operator[] (int i) const {
      return container::data_[i];
   }
   Vec& operator +=(const Vec &rop){
      for(size_t i = 0; i < size(); i++)
         container::data_[i]+= rop.data_[i];
      return *this;
   }
   Vec& operator -=(const Vec &rop){
      for(size_t i = 0; i < size(); i++)
         container::data_[i]-= rop.data_[i];
      return *this;
   }
...

There is no problem with sum or subtraction, but what we have to do with multiplication?
We can define different type of multiplication for vector, the dot product, the cross product, pairwise multiplication or scalar multiplication, every operation deserve a * operator. For clarity sake I’ll use a named method for dot and cross product and I’ll reserve the * operator for pairwise and scalar product.

...
   Vec& operator *=(const T &rop){
      for(size_t i = 0; i < size(); i++)
         container::data_[i]*= rop;
      return *this;
   }
   Vec& operator *=(const Vec &rop){
      for(size_t i = 0; i < size(); i++)
         container::data_[i]*= rop.data_[i];
      return *this;
   }
...

Dot product is a binary operation, so it’s better to make it extern to the class, same thing for cross product.

template<class container, typename T>
T dot(const Vec<container, T>& rOp, const Vec<container, T>& lOp)
{
  T ret(0);
  for(size_t i = 0; i < container::len; i++)
     ret += rOp[i] * lOp[i];
  return ret;
}

We can specialize the cross funtion to make is more efficient

template<typename T>
Vec3<T> cross(const Vec3<T>& rOp, const Vec3<T&>& lOp)
{
    Vec3 res;
    res.x = rOp.y * lOp.z - rOp.z * lOp.y;
    res.y = rOp.x * lOp.z - rOp.z * lOp.x;
    res.z = rOp.x * lOp.y - rOp.y * lOp.x;
    return res;
}

Other function like normalize, length and binary operator are trivial, you can implement them as exercise. 😛
Final touch:

typedef Vec3 Vec3f;
typedef Vec3 Vec3i;
typedef Vec3 Vec3ui;
typedef Vec2 Vec2f;
typedef Vec2 Vec2i;
...

Edit: I notice that a lot of compiler don’t like template of template, so I modify the code a little bit.

Glus for linux

Recently Norbert Nopper have released GLUS, a framework similar to (free)Glut. The first version was only for windows, but recently Pablo Alonso-Villaverde Roza wrote a version that work with X11.

I have tested this evening on Ubuntu 9.10 with a G8800 and it works perfectly.

How to build the code

GLUS use Glew to load all the openGL extension, the Glus packet that you download from the site already include Glew. But if you have Glew already installed it can generate some conflict. The Glew library that came with Ubuntu is not the most recently updated and support openGL up to 3.0. So you can remove Glew and use the one that came with Glus or download the latest Glew source and build it by yourself (it take 5 min.)

svn co https://glew.svn.sourceforge.net/svnroot/glew/trunk/glew glew
cd glew
#Probably you will need these package
sudo apt-get install libxmu-dev xorg-dev
make extensions
sudo make install

Now you can go in you Glus directory and type

make all

Now you can run the examples, make sure you have the latest driver installed.

About Glus

I’m not a big fan of Glut, it imposes a programming style that leads to a tons of global variables (I’ll write an article about that)  but is very simple and for a rough test is very good. Glus use the same program style but removing all the deprecated stuff and add some utility function to:

  • create openGL 3.2 context
  • read and create shaders from files
  • operate on matrix and vector
  • load TGA texture
  • create some basic shapes (cubes, sphere, plane)

Pro:

  • Very easy to learn, if you already had programmed with glut you don’t have to learn anything new.
  • First framework that support openGL 3.2 natively.

Cons:

  • Very young, no documentation yet.
  • It’s not object oriented
  • No support for multi-threading
  • No license… MIT? ZLIB? Need to ask.

I still don’t know why people in 2010 don’t program with object, but I think it’s a matter of taste. The lack of documentation is fullfilled by some example. I’m a bit worried about the license I hope it will adopt LGPL3.

Conclusion

IMHO Glus is very good to create some basic example, with the utility function you don’t have to bother about texture loading or shader creation, making prototyping faster. I don’t know if it’s good to create more complex program. In this case you usually create your own code for matrix, image and shader manipulation, also it lack of multi-thread support that really limit the possibilities.

Another developement blog?

When you create something new you always must ask yourself “We really need that stuff? Is original? Why I can’t use $otherProduct instead?”

We really need another blog?

Well I think that the world can survive even without my effort but that will be less funny for me, and maybe someone can find this blog useful.

Is original?

No, there is a tons of developer blogs that speak about every part of programming, and a lot of them are much more expert than me. But sometime I found some hole in the Web knowledge, in that case I try to fill that hole. This blog is my 2 cent on computer graphics, I won’t try to be the new openGL guru that know everything about graphics, but just a place when I can share and discuss about my project and my ideas.

Why I can’t follow other blogs/web pages?

Yes you can.. no you must!! I’ll give reference when I extract some part of article from another site. Internet is for collaboration 😉

I only hope that if somebody use my stuff will give me a reference.

What will you talking about in this blog? And why in English?

About the development of my project hosted in my site, some basic tutorial and news about programming, graphics and maybe maths.

I choose English cause almost every programmer (can|should) read English even Italian one. Is also a good exercise for me.

What will you not talking about?

Obsolete stuff. The main reason I open this blog is cause on the Web you can find a lot of tutorial about openGL 1972 and very few tutorial about openGL 3.x. OpenGL will not evolve if users keep using the obsolete stuff.

Can I comment your post?

Yes, but I have to approve your comment before it’s show. Don’t worry I’ll approve every comment that don’t look like spam and is somewhat in topic.

Why you create your site in you living room server? Is full of free host out there.

Cause I’m a nerd… ehm… cause I already have a SVN server for my project, and I don’t want to use another server for the blog in this way I can install any plug-in I find useful.

Sometime you can find the server off-line (cause ADSL problem, power supply problem or hardware failure). Don’t panic!!

Twitter connection active

Here a new post, this one should be visible on twitter… facebook and linkeding.

I still have problem with wp-syntax stylesheet. 😦

Hello world!

//
One two three test, this is my new blog hosted in my living room.

I’ll basically post some code, news and idea about programming and openGL

Test for wp-syntax

template<typename T, unsigned int Size>
void identity(T* matrix)
{
  for(unsigned int i = 0; i < Size; i++)
    for(unigned int j = 0; j < Size; j++)
      matrix[i+j*size] = (i==j)?T(1):T(0);
}

The post are also connected with twitter, so you can follow my activity without problem (and I can follow you).

Test Latex for wordpress:
delim{[}{matrix{3}{3}{1 2 3 4 5 6 7 8 9}}{]}
S(f)(t)=a_{0}+sum{n=1}{+infty}{a_{n} cos(n omega t)+b_{n} sin(n omega t)}

If you see a green rectangle wegGL is working. Otherwise read this.
[wgl id=’wglcontex’ width=500]