1. 程式人生 > >Bullet物理引擎教程: helloworld

Bullet物理引擎教程: helloworld

Bullet教程: Hello World 例項

歡迎加qq群 52821727 討論更多關於Bullet的東西

這篇文章裡我們將盡可能簡單的向你展示怎麼使用Bullet, 怎樣初始化Bullet, 設定一個動力學世界, 還有一個球落向地表 這個對鑑別你的build是否成功非常有用並且也能夠讓你快速的學習到Bullet的API. 首先,我們假設你的Bullet已經正確安裝並且正確設定了Bullet的include路徑(例如. /usr/local/include/bullet) 確保能連線到正確的lib. 否則請參閱Installation安裝. 如果你用的是gcc來編譯,請確保你的靜態庫反序,就是說. dynamics, collision, math.

初始化程式

以一個標準的hello world程式開始:

#include <iostream>
        int main ()
        {
                std::cout << "Hello World!" << std::endl;
                return 0;
        }

建立世界

現在我們要新增一個子彈(Bullet)模擬. 首先寫入以下語句:

#include <btBulletDynamicsCommon.h>

我們想把btDiscreteDynamicsWorld 例項化但是在做此之前我們還需要解決一些其他事情. 對於一個“hello world”例子來說它太複雜我們並不需要. 但是,為了能更符合我們自己的工程, 他們可以用來微調(fine-tuning)模擬環境.

我們需要指出使用什麼樣的 Broadphase algorithm(寬相演算法). 選擇什麼樣的泛型演算法很總要,如果有許多剛體在繪製場景裡, since it has to somehow check every pair which when implemented naively(天真) is an O(n^2) problem.

寬相(broadphase)使用 傳統的近似物體形狀並且被稱之為代理.我們需要提前告訴子彈最大的代理數, 所以才能很好的分配記憶體避免浪費. 下面就是世界裡任何時候的最大剛體數.

int maxProxies = 1024;

一些 broadphases 使用特殊的結構要求世界的尺度提前被告知, 就像我們現在遇到的情況一樣. 該broadphase可能開始嚴重故障,如果離開這個物體體積. 因為 the AxisSweep broadphase quantizes 空間基於我們使用的整個空間的大小, 您想這差不多等於你的世界.

使它小於你的世界將導致重大問題, 使它大於你的世界將導致低劣的效能.這是你程式調整的一個簡單部分, 所以為了確保數字的正確多花點時間也不防.

在這個例子中,世界從起點開始延伸10公里遠。

btVector3 worldAabbMin(-10000,-10000,-10000);
btVector3 worldAabbMax(10000,10000,10000);

這個broadphase是我們將要使用的, 這個執行的是掃描和裁剪, 這裡可以看到更多解釋Broadphase .

btAxisSweep3* broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);

該broadphase是一個極好的空間以消除不應碰撞的成隊物體. 這是為了提高執行效率.

您可以使用碰撞排程註冊一個回撥,過濾器重置broadphase代理,使碰撞系統不處理系統的其它無用部分

碰撞配置可以讓你微調演算法用於全部(而不是不是broadphase )碰撞檢測。這個方面現在還屬於研究階段

btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);

我們還需要一個"solver". 這是什麼原因導致物體進行互動得當,考慮到重力,遊戲邏輯等的影響,碰撞,會被制約。

它工作的很好,只要你不把它推向極端,對於在任何高效能模擬都有瓶頸有一些相似的可以執行緒模型:

btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;

終於我們可以初始化了世界了:

btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);

很明顯我們把重力方向設定成了Y軸的負方向,即Y軸是像上的

dynamicsWorld->setGravity(btVector3(0,-10,0));

子彈的政策是“誰分配,也刪除” 記住,必須符合這樣的結果

在main()後記的刪除.

我們提供了一個通用的結果. 程式碼如下:

#include <btBulletDynamicsCommon.h>
#include <iostream>

int main () {
    std::cout << "Hello World!" << std::endl;
 
    // Build the broadphase
    int maxProxies = 1024;
    btVector3 worldAabbMin(-10000,-10000,-10000);
    btVector3 worldAabbMax(10000,10000,10000);
    btAxisSweep3* broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);
 
    // 設定好碰撞屬性 和排程
    btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
    btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
 
    // 實際上的物理模擬器
    btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
 
    // 世界.
    btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
 
    // 這裡做一些你想做的事
 
    // 作為一個好的程式設計習慣 做好刪除工作
    delete dynamicsWorld;
    delete solver;
    delete dispatcher;
    delete collisionConfiguration;
    delete broadphase;
 
    return 0;
}


碰撞包圍體

我們將創造一個接地平面[靜態剛體] ,和一個球體,將屬於在地上[動態剛體] 。每個剛體需要參考碰撞包圍體. 碰撞包圍體只解決碰撞檢測問題, 因此沒有質量,慣性,恢復原狀等概念. 如果您有許多代理,使用相同的碰撞形狀[例如每飛船模擬是一個5單元半徑範圍]。這是個好做法,只有一個子彈形狀的碰撞,並分享它在所有這些代理. 但是我們這裡的兩個剛體形狀都不一樣,所以他們需要各自的shape.

地面通常是向上的並且裡原始點1米的樣子. 地面會和遠點交叉,但子彈不允許這樣做,

因此,我們將抵消它的1米和用來彌補,當我們把剛體設定好以後。

btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),1);

我們將讓它從天上掉下來,它是一個球體,半徑為1米.

btCollisionShape* fallShape = new btSphereShape(1);

這裡需要做碰撞形狀的清理工作.

剛體

在,我們可以新增形狀的碰撞到我們的現場,並將它們定位.

讓我們先初始化地面. 它的方向是特定的, 子彈的四元數形式 x,y,z,w . 位置在地面下一米, 將要補充一米我們不得不做的. 運動狀態在這裡可以得到詳細的說明:MotionStates

btDefaultMotionState* groundMotionState =
                new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,-1,0)));

在第一個和最後一個引數,在下面的建構函式中是質量和地表的慣性. 由於地面是靜止的所以我們把它設定成0. 固定不動的物體,質量為0 -他是固定的.

btRigidBody::btRigidBodyConstructionInfo
groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0));
btRigidBody* groundRigidBody = new btRigidBody(groundRigidBodyCI);


最後我們把地面加到世界中:

dynamicsWorld->addRigidBody(groundRigidBody);

新增下跌領域非常相似。我們將其置於50米以上的地面.

btDefaultMotionState* fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,50,0)));

由於它是動態剛體,我們將給予質量1公斤。我不記得如何計算一個球體的慣性,但是,這並不重要,因為子彈提供它的實現

btScalar mass = 1;
btVector3 fallInertia(0,0,0);
 fallShape->calculateLocalInertia(mass,fallInertia);

現在,我們可以建造剛體只是像以前一樣,並把它加到世界中:

btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass,fallMotionState,fallShape,fallInertia);
btRigidBody* fallRigidBody = new btRigidBody(fallRigidBodyCI);
dynamicsWorld->addRigidBody(fallRigidBody);

一個快速的解釋btRigidBody::btRigidBodyConstructionInfo是為了; 物體的構建是通過某些引數的. 這是通過一個特殊的結構實現的。 該部分的btRigidBodyConstructionInfo被複制到物體當你建造的時候,並只用於在初始化的時候. 如果你想建立幾千個屬性一樣的物體, 你只需要建立一個btRigidBodyConstructionInfo, 並通過它建立所有的.

開始模擬

這就是有趣的開始。我們會加強模擬200倍,間隔60赫茲. 這使它有足夠的時間降落的地面上. 每一步, 我們都會打印出它離地面的高度.

這stepSimulation 在做你所期待, 不過他的介面確實很複雜. 讀Stepping The World 以獲得更多訊息.

進後,我們審查的狀態下降領域.位置和方向都封裝在btTranform物件,我們摘錄下降領域的運動狀態. 我們只關心位置,我們退出變換getOrigin ( ) 。然後,我們列印y組成部分的立場載體.

for (int i=0 ; i<300 ; i++) {
       
                dynamicsWorld->stepSimulation(1/60.f,10);
               
                btTransform trans;
                fallRigidBody->getMotionState()->getWorldTransform(trans);
       
                std::cout << "sphere height: " << trans.getOrigin().getY() << std::endl;
        }

這應該產生一個輸出看起來像這樣的東西:

sphere height: 49.9917

        sphere height: 49.9833

        sphere height: 49.9722

        sphere height: 49.9583

        sphere height: 49.9417

        sphere height: 49.9222

        sphere height: 49.9

        ...

        sphere height: 1

        sphere height: 1

        sphere height: 1

        sphere height: 1

        sphere height: 1

看起來不錯迄今。如果你圖這對輸出迭代次數,你就會得到這個:


這個球體開始於地表的一米處. 這是因為取的是幾何中心並且它的半徑為1米. 這個球剛開始會有一個大的反彈然後漸漸的減緩彈起高度.

這是可以預料的實時物理引擎,但它可以儘量減少,增加頻率的模擬步驟

. 試試再說!

現在你可以把這個動態世界代入你的程式 實時繪製出這個球體. 也可以看看其他的 Collision Shapes . 試試一堆盒子 或者圓柱體然後用一個球去扔向他們.

完整程式碼

#include <iostream>
 
#include <btBulletDynamicsCommon.h>
 
int main (void)
{
 
        btVector3 worldAabbMin(-10000,-10000,-10000);
        btVector3 worldAabbMax(10000,10000,10000);
        int maxProxies = 1024;
        btAxisSweep3* broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);
 
        btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
        btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
 
        btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
 
        btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
 
        dynamicsWorld->setGravity(btVector3(0,-10,0));
 
        btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),1);
 
        btCollisionShape* fallShape = new btSphereShape(1);
 
        btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,-1,0)));
        btRigidBody::btRigidBodyConstructionInfo
                groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0));
        btRigidBody* groundRigidBody = new btRigidBody(groundRigidBodyCI);
        dynamicsWorld->addRigidBody(groundRigidBody);
 
        btDefaultMotionState* fallMotionState =
                new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,50,0)));
        btScalar mass = 1;
        btVector3 fallInertia(0,0,0);
        fallShape->calculateLocalInertia(mass,fallInertia);
        btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass,fallMotionState,fallShape,fallInertia);
        btRigidBody* fallRigidBody = new btRigidBody(fallRigidBodyCI);
        dynamicsWorld->addRigidBody(fallRigidBody);
 
        for (int i=0 ; i<300 ; i++) {
                dynamicsWorld->stepSimulation(1/60.f,10);
 
                btTransform trans;
                fallRigidBody->getMotionState()->getWorldTransform(trans);
 
                std::cout << "sphere height: " << trans.getOrigin().getY() << std::endl;
        }
 
        dynamicsWorld->removeRigidBody(fallRigidBody);
        delete fallRigidBody->getMotionState();
        delete fallRigidBody;
 
        dynamicsWorld->removeRigidBody(groundRigidBody);
        delete groundRigidBody->getMotionState();
        delete groundRigidBody;
 
        delete fallShape;
 
        delete groundShape;
 
        delete dynamicsWorld;
        delete solver;
        delete collisionConfiguration;
        delete dispatcher;
        delete broadphase;
 
        return 0;
}


相關推薦

Bullet物理引擎教程: helloworld

Bullet教程: Hello World 例項 歡迎加qq群 52821727 討論更多關於Bullet的東西 這篇文章裡我們將盡可能簡單的向你展示怎麼使用Bullet, 怎樣初始化Bullet, 設定一個動力學世界, 還有一個球落向地表 這個對鑑別你的build是否成功非常有用並且也能夠讓你快速

Bullet 物理引擎學習筆記(1) -- HelloWorld 詳解

本文將對 Bullet 例程 HelloWorld 中的各語句,分析其內部的操作過程。 首先是包含了標頭檔案: #include "btBulletDynamicsCommon.h" 1、首先定義了用於配置碰撞的 btCollisionConfigur

整合Bullet物理引擎到Ogre on iPhone

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Bullet物理引擎不完全指南 Bullet Physics Engine not complete Guide

                前言    Bullet據稱為遊戲世界佔有率為第三的物理引擎,也是前幾大引擎目前唯一能夠找到的支援iPhone,開源,免費(Zlib協議,非常自由,且商業免費)的物理引擎,但是文件資料並不是很好,Demo雖然多,但是主要出於特性測試/展示的目的,會讓初學者無從看起,一頭霧水。我

Bullet 物理引擎 簡析

作者: 馬良 (www.iphonephysics.com )  前提假設     計算機圖形學中的物理模擬實際上只是追求視覺近似,而並非精確的物理模擬     同時物理引擎從簡化計算考慮, 不與渲染引擎共享物件資料採用獨立的一套資料. 1 架構分析   物理模擬的基礎是建

bullet物理引擎-配置

Bullet物理引擎-配置 如下圖: 選擇第一個bullet2.82-r2704(這個是sdk)。 下載後解壓,如圖: 此時lib資料夾下只有一個readme.txt。 進入build資料夾下,如圖:          執行vs2010.bat,會在當前目錄下生成一個

bullet物理引擎與OpenGL結合 匯入3D模型進行碰撞檢測 以及畫三角網格的坑

原文作者:aircraft 原文連結:https://www.cnblogs.com/DOMLX/p/11681069.html         一.初始化世界以及模型 /// 衝突配置包含記憶體的預設設定,衝突設定。高階使用者可以建立自己的配置。 btDefault

【Cocos Creator實戰教程(8)】——打磚塊(物理引擎)

轉自:http://blog.csdn.net/potato47/article/details/73197021失蹤人口迴歸 本篇教程要基於Cocos Creator1.5的物理引擎,編寫一個簡單的打磚塊遊戲,儘可能多講一點,但現在已經快11點了,我12點要睡覺啊,好像又講

PhysX物理引擎(入門教程) —— PhysX,Hello World!

只對註冊使用者開放下載。註冊是免費的,但好像要經過稽核才會開通,不過一般都會通過的。我註冊的時候好像是第二天才收到開通郵件。有兩個安裝檔案是必須下載的System Software.exe和PhysX 2.3.3 SDK Core.exe前一個是底層驅動,後一個是程式核心,最新的SDK是2.4.1,但是隻針對

Cocos2d-x教程(17)-Box2D 物理引擎

 歡迎加入 Cocos2d-x 交流群: 193411763 轉載時請註明原文地址: 物理引擎並非每款遊戲的必需品,但它卻可以更好的模擬現實世界的真實感。 此篇文章我們將初步講解Box2D的使用方法。 想要精通Box2D並非簡單的事情,但簡單的使用Box2D卻

Bullet Physics Engine(物理引擎)中使用約束

Bullet(version 2.77)中提供了6中基本的約束: 點點約束btPoint2PointConstraint鉸鏈約束btHingeConstraint滑動約束btSliderConstraint錐形約束btConeTwistConstraint通用的6自由度約束

Bullet physics物理引擎學習筆記

Bullet 物理引擎的參考文件比較少,主要是通過學習Bullet自帶的例子來學習。以下是我在學習中遇到的一些困惑和自己的理解: 1. collisionshape和rigidbody的區別: 碰撞形狀顧名思義只需要指定碰撞體的形狀,常用的碰撞體形狀有:btBoxShape

物理引擎Havok教程

 在例子中,我用了開源的Ogre作為渲染引擎。如果你想撇開圖形渲染,只看Havok模擬的程式碼,可以參看Havok中自帶的一個例項StandAloneDemos。 一、類HavokSystem  例子中類HavokSystem封裝了Havok初始化和執行程式碼。它初始化基本庫和多執行緒模擬,並建立物理世界

IOS開發——手勢 &amp; 傳感器 &amp; 物理引擎

github上 content 物理 alt img .net amp 技術分享 lan 這次思維導圖比較雜,demo已經所有上傳到github上,小編的github地址是:狂戳 先看下效果圖: 手勢畫板: 物理引擎: 傳感器: IOS開發——手

實例介紹Cocos2d-x中Box2D物理引擎:碰撞檢測

函數實現 pda creates pty blank oid rtu and 重構 在Box2D中碰撞事件通過實現b2ContactListener類函數實現,b2ContactListener是Box2D提供的抽象類,它的抽象函數:virtual void BeginC

chipmunk 物理引擎的基本概念和基本用法

num 碰撞回調 2.0 ddb mat sha print 單獨 得出 chipmunk是一個開源2D物理引擎, 項目主頁:http://code.google.com/p/chipmunk-physics/ 工作需要研究了一下,這個引擎的資料還是不多,我閱讀了

實例介紹Cocos2d-x中Box2D物理引擎:HelloBox2D

pre all align 討論 響應 算法 站點 virtual origin 我們通過一個實例介紹一下。在Cocos2d-x 3.x中使用Box2D物理引擎的開發過程,熟悉這些API的使用。這個實例執行後的場景如圖所看到的,當場景啟動後,玩家能夠觸摸點擊屏幕,每次觸

[js高手之路]Node.js模板引擎教程-jade速學與實戰3-mixin

函數 .cn ima images ade 高手 js模板引擎 ron pan 強大的mixin mixin類似於函數的功能,可以達到模塊復用的效果 mixin show: 定義一個類似函數的功能,名字叫show,裏面的就是他的內容 +show: 調用show,每

[js高手之路]Node.js模板引擎教程-jade速學與實戰2-流程控制,轉義與非轉義

title 學習 != 下一步 cas ase spa back name 一、轉義與非轉義 jade模板文件代碼: 1 doctype html 2 html 3 head 4 meta(charset=‘utf-8‘)

[js高手之路]Node.js模板引擎教程-jade速學與實戰4-模板引用,繼承,插件使用

node.js ade 方法 頭部 containe jade bsp 繼承 for 一、block 模塊復用 把需要復用的模塊用block定義 block後面跟上模塊的名字,引用一次block 內容就會被復用一次 編譯之後的結果: 二,繼承模板(exten