2010年6月20日星期日

To render the vertex

目的是用OpenGL 3.2来画东西, 而不是glVertex, glColor.


Step 1:
准备Vertex Data:
(1). vertex count 有多少个数据? (2). 具体的vertex data, (3)这些数据的大小(in byte)
例如:
const GLint coordinateLineVertexCount = 6;
const GLint coordinateLineVertexSize = sizeof(dgp::vec3f) * 2 * coordinateLineVertexCount;
dgp::vec3f coordinateLineVertexData[] = {
// vertex position // vertex color
dgp::vec3f(0, 0, 0), dgp::vec3f(1, 0, 0),
dgp::vec3f(fLength, 0, 0), dgp::vec3f(1, 0, 0),

dgp::vec3f(0, 0, 0), dgp::vec3f(0, 1, 0),
dgp::vec3f(0, fLength, 0), dgp::vec3f(0, 1, 0),

dgp::vec3f(0, 0, 0), dgp::vec3f(0, 0, 1),
dgp::vec3f(0, 0, fLength), dgp::vec3f(0, 0, 1)
};
注意每一个vertex data包含了两部分, position and color.

Step 2:
生成一个buffer object放这些vertex data.

Step 3:
生成一个shader program,


Step 4:
当真正需要render的时候, 往shader program的相应的location里面写入对应的数据.
例如: projection matrix, model view matrix, the vertex data (position, normal, color) ....
然后指定画成什么primitive形式。

使用glVertex的特点是容易入手, 现在需要自己手工来完成上面好几个steps才可以。但是特点是思路很清晰,先打包好vertex data,往shader program里面放这些数据,条理清晰。

相对于glColor来给出顶点的颜色, 在shader里面的做法 我用了下面三种最简单的(每一种对应一个shader program):


例如图中的Grid,all the vertices are the same color, they are same color in fragment too, 所以我在fragment shader中用了一个uniform vec3 fragmentColor;程序中指定这个颜色,黑色,就ok了。

例如图中的coordinate system line,一个红线,一个绿色的线,一个蓝色的线。就需要每一个vertex 给出 color 信息. vertex shader 中:
in vec3 position;
in vec3 color; // 之后取他们的location并写入准备好的data.

例如图中的Cube, 用Blinn Phong lighting,fragment shader中计算color.




2010年6月18日星期五

Thinking about Singleton

1. The constructor should not have parameters?
In the GoF Design Patterns, there is no parameter for the constructor. That makes it very easy, because the constructor is invoked by the instance() method, if the constructor needs parameters, do we send the parameters to the instance() method, which pass them to the constructor? It is not clean and clear.

class Singleton {
public:
static Singleton *instance();
protected:
Singleton();
private:
static Singleton *s_pInstance;
};

But if the the constructor do need some parameters, how to do that?

2. The constructor need to be protected/privated?
In the GoF Design Patterns, the constructor is protected, which make sure that the clients (from outside) can not instantiate objects directly.
But if we want to create a new Singleton instance?

class Singleton {
public:
static Singleton* createNewInstance();
static Singleton* instance();
protected:
Singleton();
private:
static Singleton *s_pInstance;
};

The following is an example. For example, a new scene is created whenever a scene file is loaded/read.
Scene* Scene::s_pThis= 0;
Scene* Scene::instance() {
if (s_pThis) {
return s_pThis;
} else {
return createNewScene();
}
}
Scene* createNewScene() {
if (s_pInstance ) {
// delete, this will call the deconstructor.
delete s_pThis;
s_pThis= 0;
}
s_pThis= new Scene;
return s_pThis;
}

In this case, the instance() returns the object instance which is active, others are discarded.
And in this case, we can change it a little bit:
(1) firstly, call this method to create instance.
static Singleton* createNewInstance(...parameters...);
(2) call the instance() use the instance object.
This makes a assumption that, create it before you use it.

3. The copy constructor and assignment operator ?
See this example:
Scene s = *Scene::instance(); // this will call the copy constructor.
Scene s; // this will call the default constructor.
void functionX(Scene s) {
s is a temp instance object...
}
functionX(*Scene::instance()); // this will call the copy constructor;
Maybe, it would be safer to private these two methods.

4. How about the s_pInstance in derived class?

2010年6月16日星期三

Math Series - Quadratic equation

Ax^{2} + Bx+C=0
the solutions are:
\frac{B\pm \sqrt{B^{2} -4AC} }{2}
初中的二次方程啊:-) 我们都知道怎么解,但是有没有想过怎么建立这个方程式呢?It is meaningless until we know how to build it.

Case 1. Points on a sphere, and Ray - Sphere intersection.

2010年6月11日星期五

Bug Series - 无效的int变成了有效的unsigned char

Today, i came across this kind of bug:

int iIndex = -1 ;// -1 means invaluable value. >=0 means valuable.

unsigned char ucIdx = iIndex;

if (ucIdx >= 0) { // this is error-prone, most of time ucIdx >= 0 is true.
do sth here;
}

When iIndex = -1, the ucIdx is 255, so even you think iIndex is invaluable, but the ucIdx >= 0 is ture, so error happens.
Why?
Take a two bits value as an example. 2 bits can express 4 values,
unsigned: 00, 01, 10, 11
0, 1, 2, 3.
signed: 11, 00, 01, 10
-1, 0, 1, 2.
It is clear that the signed value -1 means 3 at unsigned value.
so, the ucIdx = iIndex = -1 means 255, which obviously/obviously >= 0. The bug comes from here.



Bug Series - 数组变小了

Let see look the a tree structure first:
一个Scene底下有两个geometry, 后来在Scene下还多建立了一个Skeleton来做skinning, 这个skinning与那两个geometry有关,是作用于它们上面的, 具体的skinning操作变换在各自的SkeletonReference中。
并且为了记录这个Skeleton 是操作哪些Geometry的,于是Skeleton有一个成员m_arrGeo[]是一个数组, 这个例子中记录的是两个指针.

下面的问题是: 我要删除这个skinning操作, 也就是将Skeleton和两个SkeletonReference删除掉.

code:
for (int i = 0; i < skeleton->m_arrGeo.size(); ++i) {
delete skeleton->m_arrGeo[i]->skeleton_reference;
}
delete skeleton;

这个代码段在Skeleton只作用于一个Geometry时候运行正常, 但是当作用于两个和多个Geometry时候就错误了(错误是隐晦地遗留到后面别的地方才造成的,不是在这里就造成,这才是恐怖的地方).

for (int i = 0; i < skeleton->m_arrGeo.size(); ++i) {
print out the size = 2;
delete skeleton->m_arrGeo[i]->skeleton_reference;
print out the size = 1;
}
delete skeleton;

可见问题在于 after executing the blue line, one element has been removed from the array. so let take a look at the de-constructor of SkeletonReference.
~SkeletonReference() {
find if the parent (the Geometry_i) is in the m_arrGeo[],
if yes, remove it.
}
Actually, this method makes sense, because when a geometry do not possess a SkeleteReference, there is no need to be recorded in the m_arrGeo[] array.

So, the problem is in the for sentence.
for (int i = 0; i < skeleton->m_arrGeo.size(); ++i) {
// we are iterating a dynamic array.
// we can not make sure that we can visit all the elements.
...
}
change it to:
std::vector<Geometry *> arrGeo = skeleton->m_arrGeo;
for (int i = 0; i < arrGeo.size(); ++i) {
// this is right.
delete arrGeo[i]->skeleton_reference;
}



2010年6月7日星期一

ComboBox - model/view

array E[]中有一些元素,希望放到一个ComboBox中可以让用户来选择用哪一个.
但是有时候E中有些元素有不想显示在ComboBox中.
这里的解决方法是将某一部分ei作为itemI, 当用户选择了某一个item时候返回其string,再到E中找对应的idx.