2015年1月13日 星期二

[String Matching] Suffix Array and Suffix Tree

[Suffix Array]


Suffix Array(a.k.a. SA) is a sorted array of all suffixes of a string.
Suffix Array(簡稱SA)是一個字串的所有suffix排序後存起來的陣列,例如:

String S = "banana$"

All of its suffixes are listed below
S的所有suffix都列在下方:

row isuffix
1 banana$
2 anana$
3 nana$
4 ana$
5 na$
6 a$
7 $

After sorting in lexicographical order will looked like this
以字母順序排序後看起來會像是這樣:

row isuffix
7 $
6 a$
4 ana$
2 anana$
1 banana$
5 na$
3 nana$

So, the SA of S is 
所以S的SA是
{ 7, 6, 4, 2, 1, 5, 3 }

[Suffix Tree]

We still use S = "banana$" as our example
我們仍然用S = "banana$"做為我們的範例

The root is empty and the smallest of its child should be on the left subtree and the larger should be on the right subtree.
Root必須是空的,且ROOT最小的child要被放在左邊,最大的要在右邊

First, we put the root and its smallest child on the graph
首先,我們把ROOT和其最小的child放在圖上


The next one we should put on is "a$", but "ana$" and "anana$" both start with "a", so we draw like this:
我們下個要放的應該是"a$",但是"ana$" 和 "anana$都是以"a"開頭,所以我們要這樣畫:
Clearly, we can see that if 2 or more suffixes have the same prefix, then the prefix will be their parent.
我們可以看出來兩個suffix如果有相同的prefix,那那串相同的prefix就是他們的parent。

Finally, out suffix tree with contents of SA on it will look like this:
最後,加上SA的內容後,我們的suffix tree會長成這樣:





2014年3月7日 星期五

[openGL] implementation of radiosity

以下直接略過數學公式的解釋,直接開始介紹 implementation 的方法:

[一] 原理

      將每個 face 分成多個 patch,以熱輻射的觀點,每個 patch 都會有散發出熱能,

      而每個 patch 的顏色都會被附近 patch 的熱能所散發的輻射所影響,

      form factor 就是一個能量在 patch 之間傳遞比例的影響公式

[二] 想法

      因為在 form factor 中,每個 patch 的面積、patch 跟 patch 之間相鄰的距離也會有影響,

      為了簡化計算,我們將每個 patch 的面積都設為 1,

      同時以 hemicube 的概念來假設任兩 patch 之間的距離也都是 1,如此簡化計算。

      另外一個問題是某兩個 patch 不一定是面對面的情況,如圖,

      綠色面不應該傳遞熱輻射到 patch,即該 face 上所有 patch 不會影響目前 patch 的顏色

   

      因此將以 patch 所能看到的 "畫面" 來決定哪些面的 form factor 應該會影響到目前 patch。

      憑藉著這樣的概念,我們將目前這個 path 所看到的畫面切割成 8 x 8個方塊,


      又因為每個 patch 都可以看到一個切割成 8 x 8 個方塊的畫面,

      且透過之前將 form factor 簡化的方式,如此一來,對於每個 patch i 和 patch j 來說,

      因為 form factor 只要是被兩 patch 之間的距離和兩 patch 的面積所影響,

      patch i 所看到方塊 (0, 0) 傳過來的能量比例跟 patch j 所看到方塊 (0, 0) 傳過來的相同,

      所以少去了每個 patch 都要重新計算 form factor 的情形

[三] pseudo code

      Step 1: Divide each face into many patches (squares)
                  把每一個面分成多個小方塊應該不難吧

      Step 2: Calculate the form factor of all patches
                  由上面的想法可以知道,只要計算一次就好

      Step 3: Calculate the color with form factor
                  將所看到的畫面中所有方塊的顏色乘以該方塊的 form factor
                  再加上目前 patch 的顏色後平均即為能量傳遞一次的新顏色

      Step 4: Interpolation of adjacent patches
                  因為這樣出來的情形是一格一格的,所以對相鄰的兩個 patch 做 interpolate
                  來模糊格子之間的邊界,但是範例中是去用貼圖幫我模糊掉的    

[四] 後記

      因為不好解釋,所以附上程式碼,有參考其他人做得之後再做過修改

2013年12月17日 星期二

[openGL] 人在 3D 中前後移動及往左往右看

[一] 目的

    在 openGL 中,3D 畫面是透過計算畫出模擬人的位置往某個特定的方向看,

    所看某個物體的樣貌,而更進階的,為了朔造出不僅能讓人看某個東西所得

    的影像,還能更進一步的移動人的位置,而看不一定的角度和畫面,這一篇

    主要就是在講怎麼用 openGL 的函式庫達成

    在 3D 的畫面中移動,有兩種方法,第一種,移動整個場景,但是不移動眼

    睛所在的位置及眼睛所看的地方;第二種,移動眼睛所在的位置及眼睛所看

    的地方,但是場景不移動。

[二] 移動場景,不移動眼睛座標及視角

1.    想法: 當前後移動時,非常簡單,修改場景中所有的物體的 z 值就可以達成;

                 當要換方向看時,應該要讓場景中所有物體繞著眼睛所在的方向進行公轉,

                 公轉方法可以看上一篇

        (p.s) 當看的方向改變時,移動方向也應該改變,
                                                此時只要算 sin 和 cos 就可以得到各方向的移動距離囉

2.    因為這個比較簡單,所以就不寫 pseudo code 惹 XD

[三] 不移動場景,移動眼睛座標及視角

1.    想法: 首先,先將眼睛看的位置(position)放在離眼睛(eye)距離 1 的地方,當前

                 後移動時,將 eye 和 position 的 z 值同時加減 1 即可,一樣的,當看的方

                 向不同時,一樣要算 sin 和 cos,才能得到正確的各方向移動位置;而當

                 視角改變時,則是應該固定 eye 的位置,用 sin 和 cos 去調整 position 即可

2. 這 pseudo code 反而太麻煩,不想寫 = =

[openGL] 公轉與自轉

以下介紹內容直接用太陽系的概念,所以誰繞誰轉,誰要自轉就不解釋了 XD

[一] 公轉


1.    目的: 物體或模型繞著某個點轉 (通常是原點)

2.    想法: 在 openGL 的函式庫中,glRotate*() 是繞著原點轉的,所以我們應該先計算

      出將太陽移動至原點的距離,而後讓整個太陽系的所有物體都依照這個距離移動,

      再讓地球旋轉,最後再將物體移回原來的位置

      (p.s) 測試過後,openGL 的 rotate 並不會像之前實作一樣讓整個單位向量跑掉,所以可以這樣做

3.    pseudo code:

// 畫地球
      glPushMatrix();
      glTranslate(dx, dy, dz);
      glRotate(angle, ...);
      glTranslate(-dx, -dy, -dz);
      ... draw earth ...
      glPopMatrix();

//畫月亮
      glPushMatrix();
      glTranslate(dx2, dy2, dz2);
      glRotate(angle, ...);
      glTranslate(-dx2, -dy2, -dz2);
      ... draw moon ...
      glPopMatrix();

//畫太陽
      ... draw sun ...

      //dx, dy, dz 是將 sun 移動到原點各方向所需要的距離
      //dx2, dy2, dz2 是將 earth 移動到原點各方向所需要的距離

[二] 自轉


1.    目的: 物體或模型繞著某個點轉 (通常是自己的中心點)

2.    想法: 用跟上面一樣的概念,所以要自轉的物體,一樣要先旋轉的中心點移動到坐標系中

       的原點處,而後旋轉在移回原來的位置

3.    pseudo code:

// 讓地球又公轉又自轉
      glPushMatrix();
      glTranslate(dx, dy, dz);
      glRotate(angle, ...);
      glTranslate(-dx, -dy, -dz);
      glTranslate(dx2, dy2, dz2);
      glRotate(angle, ...);
      glTranslate(-dx2, -dy2, -dz2);
      ... draw earth ...
      glPopMatrix();

      //dx, dy, dz 是將 sun 移動到原點各方向所需要的距離
      //dx2, dy2, dz2 是將 earth 移動到原點各方向所需要的距離

2013年12月9日 星期一

[openGL] glPushMatrix() 和 glPopMatrix()

首先,先說明一下,網路上查關於 openGL 的內容,常常會提到 CM,CM 是 Current Matrix 的簡寫,也就是目前 matrix 內的內容。

要了解的話,可以先從最下面「 [三] 例子」,開始看。

[一] glPushMatrix()

    1. 功能: 將 CM push 到 stack 中,而依不同的機器 stack 可以存放 matrix 的數量有所不同

    2. 目的: 為了各種原因,保存目前的 CM,等待之後再進行使用 (下面有原因的例子)

[二] glPopMatrix()

    1. 功能: pop 出 stack 中的 matrix,並且把現在的 CM 取代掉

    2. 目的: 一樣也是為了各種原因,把之前儲存在 stack 中的 matrix,讀回來繼續使用

[三] 例子

    1.

    glTranslated(0, 10, 0);
    ... draw A ...
    glPushMatrix();
    glRotatef(90, 0, 1, 0);
    ... draw B ...
    glPopMatrix();
    ... draw C ...

    : A 、 B、C 三個都會平行 y 軸移動 10 單位,只是 B 還會繞 y 軸旋轉 90 度

    : 在畫完 A 之後,CM 中保存著往 y 方向移動 10 的內容,之後 glPushMatrix() 把這
      個 CM 存進 stack 中,而第四行再把目前的 CM 旋轉 90 度,在畫完 B 之後,
      glPopMatrix() 把 stack 中向 y 方向移動 10 的內容讀取出來把目前有移動又有旋轉的
      CM 取代掉,因此 C 就只有移動了

    2.

    glTranslated(0, 10, 0);
    ... draw A ...
    glPushMatrix();
    glLoadIdentity();
    glRotatef(90, 0, 1, 0);
    ... draw B ...
    glPopMatrix();
    ... draw C ...

    : A、C 三個都會平行 y 軸移動 10 單位,B 只會繞 y 軸旋轉 90 度

    : 跟上面例子不同之處,在於 glPushMatrix() 之後,有多做一個 glLoadIdentity() 的動作,
     因為目前的 CM 就變回最剛開始的單位矩陣,什麼動作都沒有做,因此,
     B 就只有對 y 軸旋轉 90 度,之後把之前的 matrix pop回來,則現在的 CM 就有了
     移動的內容,而他對 C 做運算之後,C也有了移動的

    [總結]

    有時候可能需要把目前移動、旋轉等等的資訊記錄起來,把其他運算做完之後,

    再把原本存起來的資訊讀回來繼續使用,這時候就可以使用 glPushMatrix()、glPopMatrix(),

    (例如最近在做的小小賽車遊戲,因為是讀取 .obj 檔來使用,所以每一個模型面向的方向、
     位置等等都要再重新做設定,但是除了每一個模型自己旋轉移動到正確的位置外,
     也要能夠跟著其他模型大家一起旋轉,就非常需要這種功能)

2013年11月30日 星期六

[openGL] homework

[一] homework 1
Object:

implementation of 3 line algorithms, scan-line polygon-fill algorithm, boundary-fill algorithm, and antialiasing algorithm.


[二] homework 2

Object:

implementation of matrix transformation, back-face culling algorithm, etc...


[三] homework 3


Object: 

use functions that openGL included or functions you wrote before to design a simple car game

有簡陋的邊界判斷,之前一直在想好像沒有前進的感覺,直到DEMO時間到了,一直不知道該怎麼做出前進的感覺直到DEMO的時候老師說如果加上馬路上的白線就看的出來了我才恍然大悟,因為之前做兩次作業,老師都問怎麼不用MFC,看來她很想看我用MFC做,所以這次索性用了MFC include openGL XD


2013年11月29日 星期五

[openGL] Scan-Line Method (Surface-Visibility Algorithm) 實作

Surface-Visibility Algorithm 實作的演算法有很多,而其中我只有做過幾個,而這篇要談的是其中

的 Scan-Line Method

[一] 原文書的說法:

    To facilitate the search for surfaces crossing a given scan line, an active list of edges is formed for each scan line as it is processed. The active edge list contains only those edges that cross the current scan line, sorted in order of increasing x. In addition, we define a flag for each surface that is set to "on" or "off" to indicate whether a position along a scan line is inside or outside the surface. Pixel positions across each scan line are processed from left to right. This procedure works correctly only if surfaces do not cut through or otherwise cyclically overlap each other. If any kind of cyclic overlap is present in a scene, we can divide the surfaces to eliminate the overlaps.

(擷取部分內容)

[二] 作法

count the minimum and maximum y value of the surface to be drawn (slope of scan lines)
// scan line is a line which parallel to x axis

for each scan line {

    calculate the intersections of the boundaries and the scan line
    // assume that each surface has only 3 edges so we will get 2 intersections(x1 and x2) at most
    // than we draw pixel from (x1, scan line) to (x2, scan line)

    for each pixel to be drawn {
 
        calculate the depth (z) of the pixel (x, y) on that surface

        if z is smaller than the current depth of that pixel than
            draw the pixel with proper color and update the depth

        otherwise do nothing.

    }

}



[三] depth (z) 的算法

由面積公式可知 Ax + By + Cz + D = 0

得 z = -(Ax + By + D) / C,

下為 A、B、C 和 D 的算法,由平面上三點 (x1, y1, z1), (x2, y2, z2), and (x3, y3, z3) 計算而得