games101 作業8


差不多過了四個月(一個學期)了,這個學期太忙了,之前一直沒有寫出作業8,再加上這個學期,太折磨了,幾乎就是在荒廢時間,暑假在忙保研的事情,其實還有一個營,不過差不多就要確定了吧,於是最終在今天寫完了作業8。

同樣的,我們來看作業要求:

在 rope.cpp 中, 實現 Rope 類的構造函數。這個構造函數應該可以創建一個 新的繩子 (Rope) 對象,該對象從 start 開始,end 結束,包含 num_nodes 個節點。 每個結點都有質量,稱為質點;質點之間的線段是一個彈簧。通過創建一系列的 質點和彈簧,你就可以創建一個像彈簧一樣運動的物體。
pinned_nodes 設置結點的索引。這些索引對應結點的固定屬性 (pinned at tribute) 應該設置為真(他們是靜止的)。對於每一個結點,你應該構造一個 Mass 對象,並在 Mass 對象的構造函數里設置質量和固定屬性。(請仔細閱讀代碼,確 定傳遞給構造函數的參數)。你應該在連續的兩個結點之間創建一個彈簧,設置彈 簧兩端的結點索引和彈簧系數 k,請檢查構造函數的簽名以確定傳入的參數。
 
這個應該很簡單,我們要注意,彈簧的數量比節點的數量多一個,這樣就很簡單了,簡單向量計算即可
 Rope::Rope(Vector2D start, Vector2D end, int num_nodes, float node_mass, float k, vector<int> pinned_nodes)
    {
        // TODO (Part 1): Create a rope starting at `start`, ending at `end`, and containing `num_nodes` nodes.
        for(int i=0;i<num_nodes;i++)
        {
            Vector2D current = start + i*(end-start)/(num_nodes-1);
            Mass*  tmp = new Mass(current,node_mass,false);
            masses.push_back(tmp);
        }
        for(int i=0;i<num_nodes-1;i++)
        {
            Spring* tmp = new  Spring(masses[i],masses[i+1],k);
            springs.push_back(tmp);
        }
//        Comment-in this part when you implement the constructor
        for (auto &i : pinned_nodes) {
            masses[i]->pinned = true;
        }
    }

 

接下來是實現胡克定律和隱式/顯式歐拉,這里有一個問題,就是我的顯式歐拉似乎一直不穩定,但是隱式歐拉是穩定的

基於物理,注意,走入CGL/include 文件夾,其實我們能看到作業框架引用的一系列函數庫,計算向量的模長可以用norm()函數,而計算向量的歸一化可以用unit函數,屬實節省了不少時間。

注意,顯式的歐拉要求我們按照原來的速度算位置,而隱式先讓我們算好后面的速度然后計算最終位置

這里最令人難以理解的就是“阻尼”的計算,按照閆神課上講的,我們應該在Springs循環算每一個阻尼,作業pdf這里沒講明白,其實在論壇上助教指出很簡單,就是做一個速度的衰減就行了,具體的討論可以看這兩個帖子

HW8的一些問題 – 計算機圖形學與混合現實研討會 (games-cn.org)

關於作業8的一些問題解答 – 計算機圖形學與混合現實研討會 (games-cn.org)

 

 

 void Rope::simulateEuler(float delta_t, Vector2D gravity)
    {
        for (auto &s : springs)
        {
            // TODO (Part 2): Use Hooke's law to calculate the force on a node
            Vector2D ab = s->m2->position - s->m1->position;
            Vector2D f =  s->k *  (ab.unit()) * (ab.norm() - s->rest_length);
            s->m1->forces += f;
            s->m2->forces -= f;
        }

        for (auto &m : masses)
        {
             float k_d  = 0.1;
            if (!m->pinned)
            {
                // TODO (Part 2): Add the force due to gravity, then compute the new velocity and position
                m->forces += gravity * m->mass;
                // TODO (Part 2): Add global damping
                m->forces += - k_d * m->velocity;
                Vector2D a = m->forces / m->mass;
               /*
                    //explicit  Euler  
                m->position += m->velocity * delta_t;
                m->velocity += a * delta_t;
               */
                   //implicit Euler   
                m->velocity += a * delta_t;
                m->position += m->velocity * delta_t;
            }
            // Reset all forces on each mass
            m->forces = Vector2D(0, 0);
        
       }
    }

 

 

 

 然后是最后的顯示Verlet方法,注意我們這里會用到mass中的last_position參數,用於保存X(t-1),其實這里很簡單,就是把前面的一部分復制過來,然后按照作業要求寫出最關鍵的那一行帶阻尼的公式就行,注意用last_position進行記憶原先的值即可

 void Rope::simulateVerlet(float delta_t, Vector2D gravity)
    {
        for (auto &s : springs)
        {
            // TODO (Part 3): Simulate one timestep of the rope using explicit Verlet (solving constraints)
            Vector2D ab = s->m2->position - s->m1->position;
            Vector2D f = s->k *  (ab.unit()) * (ab.norm() - s->rest_length);
            s->m1->forces += f;
            s->m2->forces -= f;
        }

        for (auto &m : masses)
        {
            if (!m->pinned)
            {
                m->forces += gravity * m->mass;
                Vector2D a = m->forces / m->mass;

                // TODO (Part 3.1): Set the new position of the rope mass
                Vector2D temp = m->position;
                // TODO (Part 4): Add global Verlet damping
                double  damping_factor = 0.00005;
// 核心公式,帶阻尼的計算 m
->position = m->position + (1 - damping_factor) * (m->position - m->last_position) + a * delta_t *delta_t;
// 用last_position記憶原先的位置 m
->last_position = temp; } m->forces = Vector2D(0,0); } } }

 

 可以看一下最終的效果


免責聲明!

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



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