分形之萬花筒


      萬花筒是一種光學玩具,只要往筒眼里一看,就會出現一朵美麗的“花”樣。將它稍微轉一下,又會出現另一種花的圖案。不斷地轉,圖案也在不斷變化,所以叫“萬花筒”。萬花筒的圖案是靠玻璃鏡子反射而成的。它是由三面相交成60°角的鏡子組成的,由於光的反射定律,放在三面鏡子之間的每一件東西都會映出六個對稱的圖象來,構成一個六邊形的圖案.三面玻璃鏡子組成一個三棱鏡,再在一頭放上一些各色玻璃碎片,這些碎片經過三面玻璃鏡子的反射,就會出現對稱的圖案,看上去就像一朵朵盛開的花。

      記得小時候我就親手做過一個萬花筒,雖然非常簡陋,因為鏡子條是摔出來的,但做好后有種創造了另外一個世界的感覺.這一節展示下我寫的一個萬花筒的程序.程序下載地址:http://files.cnblogs.com/WhyEngine/Phantoscope.7z

      萬花筒是由三面鏡子構成,所以其圖案是一系列的三角形網格,程序中最重要的是構造這種三角形網格.下面是生成網格頂點和紋理坐標的代碼:

 1 void YcRegularTriangleGridDrawer::UpdateVB()
 2 {
 3     if (!m_pVB)
 4     {
 5         return;
 6     }
 7 
 8     Vector2 vOffset;
 9     Vertex_UV* v;
10     Yuint index;
11     Yuint odd_even;
12     m_pVB->Lock(0, 0, (void**)&v, 0);
13     {
14         for (Yuint i = 0; i <= m_uiRow; i++)
15         {
16             odd_even = (i&0x1);
17             vOffset.x = odd_even ? m_fCellSize*0.5f : 0.0f;
18             vOffset.x -= m_fCellSize*m_uiCol*0.5f;
19             vOffset.y = (m_uiRow*0.5f - i)*m_fCellSize*YD_SIN_60;
20 
21             for (Yuint j = 0; j <= m_uiCol; j++)
22             {
23                 index = i*(m_uiCol + 1) + j;
24 
25                 v[index]._x = vOffset.x + j*m_fCellSize;
26                 v[index]._y = vOffset.y;
27                 v[index]._z = 0.0f;
28 
29                 if (odd_even)
30                 {
31                     v[index]._u = m_uvTexcoords[(2+j)%3].x;
32                     v[index]._v = m_uvTexcoords[(2+j)%3].y;
33                 }
34                 else
35                 {
36                     v[index]._u = m_uvTexcoords[j%3].x;
37                     v[index]._v = m_uvTexcoords[j%3].y;
38                 }
39             }
40         }
41     }
42     m_pVB->Unlock();
43 }

頂點有了后,三角形的索引也很重要:

 1     WORD* ib;
 2     Yuint odd_even;
 3     Yuint index;
 4     m_pIB->Lock(0, 0, (void**)&ib, 0);
 5     {
 6         for (Yuint i = 0; i < m_uiRow; i++)
 7         {         
 8             odd_even = (i&0x1);   
 9             for (Yuint j = 0; j < m_uiCol; j++)
10             {
11                 index = i*m_uiCol + j;
12 
13                 if (odd_even)
14                 {
15                     ib[index*6 + 0] = (WORD)(i*(m_uiCol + 1) + j);
16                     ib[index*6 + 1] = (WORD)((i+1)*(m_uiCol + 1) + j + 1);
17                     ib[index*6 + 2] = (WORD)((i+1)*(m_uiCol + 1) + j);
18 
19                     ib[index*6 + 3] = (WORD)(i*(m_uiCol + 1) + j);
20                     ib[index*6 + 4] = (WORD)(i*(m_uiCol + 1) + j + 1);
21                     ib[index*6 + 5] = (WORD)((i+1)*(m_uiCol + 1) + j + 1);
22                 }
23                 else
24                 {
25                     ib[index*6 + 0] = (WORD)(i*(m_uiCol + 1) + j);
26                     ib[index*6 + 1] = (WORD)(i*(m_uiCol + 1) + j + 1);
27                     ib[index*6 + 2] = (WORD)((i+1)*(m_uiCol + 1) + j);
28 
29                     ib[index*6 + 3] = (WORD)((i+1)*(m_uiCol + 1) + j);
30                     ib[index*6 + 4] = (WORD)(i*(m_uiCol + 1) + j + 1);
31                     ib[index*6 + 5] = (WORD)((i+1)*(m_uiCol + 1) + j + 1);
32                 }
33             }
34         }
35     }
36     m_pIB->Unlock();

 

程序啟動后,會出現滿屏的三角形網格.

將任意一圖像文件拖入窗體內,即可看到萬花筒的樣子.

在窗體右下角會顯示拖入圖像.上面有個三角形,鼠標拖動三角形的頂點,可以改變三角形的形狀,從而改變萬花筒的視圖.

這是個3D程序,鼠標右鍵的拖動可以改變視角.


X用於恢復為默認視角.
W用於網格與萬花筒的切換.
F11用於全屏切換.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM