NeHe OpenGL教程 第三十九課:物理類比

來源:互聯網
上載者:User

標籤:connect   blog   內容   包含   定義   ued   過程   oid   執行   

轉自【翻譯】NeHe OpenGL 教程

前言

聲明,此 NeHe OpenGL教程系列文章由51部落格yarin翻譯(2010-08-19),本部落格為轉載並稍加整理與修改。對NeHe的OpenGL管線教程的編寫,以及yarn的翻譯整理表示感謝。

 

NeHe OpenGL第三十九課:物理類比

物理類比簡介:

還記得高中的物理吧,直線運動,自由落體運動,彈簧。在這一課裡,我們將創造這一切。
 
物理類比介紹

如果你很熟悉物理規律,並且想實現它,這篇文章很適合你。

在這篇教程裡,你會建立一個非常簡單的物理引擎,我們將建立以下類:

內容:

位置類
* class Vector3D --->  用來記錄物體的三維座標的類

力和運動
* class Mass --->  表示一個物體的物理屬性

類比類
* class Simulation --->  類比物理規律

類比勻速運動
* class ConstantVelocity : public Simulation --->  類比勻速運動

類比在力的作用下運動
* class MotionUnderGravitation : public Simulation --->  類比在引力的作用下運動
* class MassConnectedWithSpring : public Simulation --->  類比在彈簧的作用下運動

class Mass
{
public:
 float m;         // 品質
 Vector3D pos;        // 位置
 Vector3D vel;        // 速度
 Vector3D force;        // 力

 Mass(float m)        // 建構函式
 {
  this->m = m;
 }

 ...
 
 下面的代碼給物體增加一個力,在初始時這個力為0

 void applyForce(Vector3D force)
 {
  this->force += force;      // 增加一個力
 }

 void init()        // 初始時設為0
 {
  force.x = 0;
  force.y = 0;
  force.z = 0;
 }

 ...

下面的步驟完成一個類比:

1.設定力
2.應用外力
3.根據力的時間,計算物體的位置和速度

 void simulate(float dt)
 {
  vel += (force / m) * dt;     // 更新速度
        

  pos += vel * dt;      // 更新位置
          
 }

類比類怎樣運作:

在一個物理類比中,我們按以下規律進行類比,設定力,更新物體的位置和速度,按時間一次又一次的進行類比。下面是它的實現代碼: 
  
class Simulation
{
public:
 int numOfMasses;        // 物體的個數
 Mass** masses;        // 指向物體結構的指標

 Simulation(int numOfMasses, float m)      // 建構函式
 {
  this->numOfMasses = numOfMasses;

  masses = new Mass*[numOfMasses];    

  for (int a = 0; a < numOfMasses; ++a)    
   masses[a] = new Mass(m);   
 }

 virtual void release()       // 釋放所有的物體
 {
  for (int a = 0; a < numOfMasses; ++a)    
  {
   delete(masses[a]);
   masses[a] = NULL;
  }

  delete(masses);
  masses = NULL;
 }

 Mass* getMass(int index)
 {
  if (index < 0 || index >= numOfMasses)    // 返回第i個物體
   return NULL;      

  return masses[index];      
 }

...

 (class Simulation continued)

 virtual void init()       // 初始化所有的物體
 {
  for (int a = 0; a < numOfMasses; ++a)    
   masses[a]->init();     
 }

 virtual void solve()       //虛函數,在具體的應用中設定各個施加給各個物體的力
 {
         
 }

 virtual void simulate(float dt)      //讓所有的物體類比一步
 {
  for (int a = 0; a < numOfMasses; ++a)    
   masses[a]->simulate(dt);    
 }

 ...

整個類比的部分被封裝到下面的函數中 
  
 (class Simulation continued)

 virtual void operate(float dt)      //  完整的類比過程
 {
  init();        // 設定力為0
  solve();        // 應用力
  simulate(dt);       // 類比
 }
};

現在我們已經有了一個簡單的物理類比引擎了,它包含有物體和類比兩個類,下面我們基於它們建立三個具體的類比對象:

1. 具有恒定速度的物體
2. 具有恒定加速度的物體
3. 具有與距離成反比的力的物體

在程式中控制一個類比對象:

在我們寫一個具體的類比類之前,讓我們看看如何在程式中類比一個對象,在這個教程裡,類比引擎和操作類比的程式在兩個檔案裡,在程式中我們使用如下的函數,操作類比:

void Update (DWORD milliseconds)      // 執行類比

這個函數在每一幀的開始更新,參數為相隔的時間。 
  
void Update (DWORD milliseconds)
{
 ...
 ...
 ...

 float dt = milliseconds / 1000.0f;     // 轉化為秒

 dt /= slowMotionRatio;      // 除以類比係數

 timeElapsed += dt;       // 更新流失的時間

 ...

在下面的代碼中,我們定義一個處理間隔,沒隔這麼長時間,讓物理引擎類比一次。 

 ...

 float maxPossible_dt = 0.1f;     // 設定類比間隔
         

   int numOfIterations = (int)(dt / maxPossible_dt) + 1;   //計算在流失的時間裡類比的次數
 if (numOfIterations != 0)     
  dt = dt / numOfIterations;     

 for (int a = 0; a < numOfIterations; ++a)    // 類比它們 
 {
  constantVelocity->operate(dt);     
  motionUnderGravitation->operate(dt);    
  massConnectedWithSpring->operate(dt);    
 }
}

下面讓我們來寫著兩個具體的類比類:

1. 具有恒定速度的物體
* class ConstantVelocity : public Simulation ---> 類比一個勻速運動的物體

class ConstantVelocity : public Simulation
{
public:
 ConstantVelocity() : Simulation(1, 1.0f)    
 {
  masses[0]->pos = Vector3D(0.0f, 0.0f, 0.0f);   // 初始位置為0
  masses[0]->vel = Vector3D(1.0f, 0.0f, 0.0f);   // 向右運動
 }
};

下面我們來建立一個具有恒定加速的物體:

class MotionUnderGravitation : public Simulation
{
 Vector3D gravitation;       // 加速度

 MotionUnderGravitation(Vector3D gravitation) : Simulation(1, 1.0f)  //  建構函式
 {         
  this->gravitation = gravitation;     // 設定加速度
  masses[0]->pos = Vector3D(-10.0f, 0.0f, 0.0f);   // 設定位置為左邊-10處
  masses[0]->vel = Vector3D(10.0f, 15.0f, 0.0f);   // 設定速度為右上
 }

 ...

下面的函數設定施加給物體的力    

 virtual void solve()       // 設定當前的力
 {
  for (int a = 0; a < numOfMasses; ++a)    
   masses[a]->applyForce(gravitation * masses[a]->m); 
 }

下面的類建立一個受到與距離成正比的力的物體: 
  
class MassConnectedWithSpring : public Simulation
{
public:
 float springConstant;       // 彈性係數
 Vector3D connectionPos;       // 串連方向

 MassConnectedWithSpring(float springConstant) : Simulation(1, 1.0f)  // 建構函式
 {
  this->springConstant = springConstant;    

  connectionPos = Vector3D(0.0f, -5.0f, 0.0f);  

  masses[0]->pos = connectionPos + Vector3D(10.0f, 0.0f, 0.0f); 
  masses[0]->vel = Vector3D(0.0f, 0.0f, 0.0f);  
 }

 ...

下面的函數設定當前物體所受到的力: 
  
virtual void solve()        // 設定當前的力
{
 for (int a = 0; a < numOfMasses; ++a)     
 {
  Vector3D springVector = masses[a]->pos - connectionPos;  
  masses[a]->applyForce(-springVector * springConstant);  
 }
}
原文及其個版本原始碼下載:

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=39

  

NeHe OpenGL教程 第三十九課:物理類比

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.