box2d學習總結

box2d HelloWorld


一、 HelloWorld


開始之前,我假想你已經看過了HelloWorld的源代碼,並看了用戶手冊中關於HelloWorld的相關說明,而且已經大致明白了大多數內容。
其實HelloWorld已經用極其簡單的語言向你描述了Box2D物理引擎的運作機制,我們可以歸納一下步驟:
1、 建立一個世界,這個世界基於一個b2AABB框,並設立了一個g值和一個是否允許休眠的bool型變量。
2、 建立一個靜態剛體地表,這裏講述了定義Box2D物理引擎中最爲重要的一個東西——剛體的詳細過程:首先是定義一個形狀(可以是複合形狀,這個在第二部分講述),然後把形狀通過AddShape添加進剛體定義,創建這個剛體。
3、 重複創建剛體這個過程,直至你沒有需求了。
4、 在你的循環中加入世界的更新函數。
其實上面的步驟也是衆多物理引擎甚至於其他引擎採用的方式。
HelloWorld教程是相當簡單的,這個時候你甚至都不用去想世界是怎麼運作的,你可以利用相關函數取得剛體的位置和旋轉角度,然後在遊戲的渲染部分去更新渲染你的角色對象。
看完HelloWorld,你可以不去想整個世界是怎樣的,因爲這個世界相對這時的你來說,確實是太複雜了,而你靜下心來時,不妨回頭看看我們用到的概念和數據類型,來溫顧一下。
概念
在這一個例子中有幾個概念,
世界(b2World):世界就是一個環境,所有物理運算都在這個裏面進行。
形狀定義(b2ShapeDef):形狀定義是什麼?說簡單點形狀定義就是定義你這個對象的樣子,它用來做什麼?就是用來確定你的碰撞。
剛體定義(b2BodyDef):剛體定義就是設定剛體的初始具體,在目前來說,最大的功能就是把你定義好的形狀加到你想到的剛體上。
剛體(b2Body):剛體就是物理引擎裏面的東西(對象),它可以受力的作用進行當前位置的變化旋轉等。你要在世界中使用的所有物體目前來說都是剛體。
類型定義
幾個類型定義(熟悉Box2D裏面的類型定義可以對我們將來正確賦值運算有着很大的幫助):
typedef signed char int8;
typedef signed short int16;
typedef signed int int32;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef float float32;
const float32 b2_pi = 3.14159265359f;
數據類型
1、 b2Vec2
就像在3D中Vector3類的使用一樣,b2Vec2在Box2D中也應用廣泛,你幾乎在每個時刻都用到它,比如說定義座標位置,定義Box大小等


b2Vec2是由float32類型的x,y組成,支持負向量,+=,-=,*=操作符,
支持的方法有
Void SetZero();設置x,y爲0
Void Set(float32 x_, float32 y_);設置x,y爲指定值
b2Vec2 Make(float32 x_, float32 y_),生成一個值指定的b2Vec2
float32 Length()取得向量的長度或模
float32 Normalize()標準化向量
bool IsValid()檢查是否有效
如果在這裏你並不瞭解我在這裏所提到的一些數學概念,比如說標準化向量,模,可以參照b2Math.h文件,或者直接找本數學書來看。




2、b2Mat22
在HelloWorld教程中,b2Mat22雖然沒有被使用到,我們這裏先提出這個概念,以便於在下一節中討論。
其實b2Mat22一個由兩個b2Vec2組成的2*2方陣,你可以直接由兩個b2Vec2(col1、col2)構造或者由一個角度值構造。
他的主要方法有:
void Set(const b2Vec2& c1, const b2Vec2& c2)
void Set(float32 angle),
提供兩種方式賦值方法
void SetIdentity(),設定恆等式
void SetZero(),把col1、col2的x,y都清爲0
b2Mat22 Invert(),轉換相關數據
b2Vec2 Solve(const b2Vec2& b),解決A * x = b


3、b2AABB


b2AABB就是一個盒子,是由兩個向量組成,一個爲minVertex是最小頂點,另一個爲maxVertex是最大頂點,通過這兩個頂點來表示最爲普通的AABB框。


4、b2ShapeDef
b2ShapeDef直翻爲形狀定義,它用一個b2ShapeType型量type來表示形狀類型,用函數指針來表示用戶數據(userdata),用一個b2Vec2向量localPosition來表示當前位置,用float32的localRotation來表示當前角度,用float32的 friction、density、restitution來表示摩擦力、密度、彈性係數,用uint16的categoryBits和maskBits 來表示碰撞位及位標識(可以用來過濾一些碰撞),用int16的groupIndex來表示組號,這個組號可以用來過濾還比位標識優先。


相關常量
enum b2ShapeType
{
e_unknownShape = -1,
e_circleShape,
e_boxShape,
e_polyShape,
e_meshShape,
e_shapeTypeCount,
};
相關形狀定義
b2CircleDef繼承於b2ShapeDef,type 爲 e_circleShape,另外帶有一個類型爲float32的量radius來表示半徑值。
b2BoxDef繼承於b2ShapeDef,type 爲 e_ boxShape,另外帶有一個類型爲b2Vec2的量extents來表示區域值。
b2PolyDef繼承於b2ShapeDef,type 爲 e_ polyShape,另外帶有一個類型爲b2Vec2的數組vertices來表示頂點,並帶有一個int32型的量vertexCount來表示頂點數,目前頂點數最多支持8個。
5、b2BodyDef
b2BodyDef是剛體定義結構,由一個函數指針userData來表示用戶數據,一組類型爲b2ShapeDef*指針數組shapes來表示形狀隊列,目前形狀數最大支持64個,用一個b2Vec2向量position來表示當前位置,用類型爲float32的量rotation來表示當前角度,用類型爲b2Vec2的量linearVelocity表示線速度,用類型爲float32的angularVelocity來表示角速度,用類型爲 float32的量linearDamping來表示線性阻尼,用類型爲float32的量angularDamping來表示角阻抗,用類型爲bool 的allowSleep 來表示是否可以允許休眠,用一個類型爲bool的isSleeping來表示是否正在休眠,用一個類型爲bool的量preventRotation來表示是否防止旋轉,支持方法:
AddShape(b2ShapeDef* shape)。


上面這些東西,其實現在沒有必要去記住,慢慢運用中就可以熟練掌握。
源文件包裏除了這個HelloWorld之外還有不少的例子,個人建議先從CompoundShapes開始。


二、CompoundShapes




CompoundShapes其實也沒有做什麼事情,相對於HelloWorld來說,我認爲,僅僅是多了一個方法的應用,即是有關b2Mat22方陣和向量的相乘應用,這裏被用來獲得轉換後的位置。
這個例子對於看過HelloWorld的你來說,應該會很簡單,只是建議看這個例子的時候再翻翻數學書,並複習一下使用到的幾種數據類型說明。


三、 VaryingRestitution、VaryingFriction、Pyramid、PolyShapes




Box2D本身所自帶的教程相當的少,前兩個例程是關於摩擦力和彈性係數的例子,也僅僅修改了相關數據,算是一種演示吧,Pyramid這個例子也就是一個簡單的例子,只是使用了Make方法來創建向量。沒什麼參考價值。
PolyShapes這個例子舉個自定義多邊形形狀的方法,你只要記住當前多邊形最多支持頂點數爲8就行了。
四、 CollisionFiltering、




碰撞過濾是用來防止形狀與形狀之間進行碰撞的,就像上文所示,它可以用碰撞種類和組名來區別,Box2D總共提供16種碰撞種類,每個形狀都可以提定屬於什麼種類,那麼它就可以和其他不同種類的形狀碰撞,如果在一個多人在線遊戲中,你想你的玩家在他們之間不進行碰撞,怪物和怪物之間不進行碰撞,但人和怪物進行碰撞,你可以使用
playerShapeDef.categoryBits = 0x0002;
monsterShapeDef.categoryBits = 0x0004;
playerShape.maskBits = 0x0004;
monsterShapeDef.maskBits = 0x0002;
碰撞組索引是一個可以大量指定物體碰撞規則的東西,你可以通過它來指定成百上千的物體,當碰撞組索引爲負數時,東西之間不碰撞,當爲正數時進行碰撞,而且碰撞組索引的優先級比碰撞種類要高。
shape1Def.groupIndex = 2;
shape2Def.groupIndex = 2;
shape3Def.groupIndex = -8;
shape4Def.groupIndex = -8;
形狀1和2就碰撞,因爲組索引大於0,而3和4不碰撞,因爲小於0
可以參考例子代碼來確定你的碰撞方法.


五、 ApplyForce




應力的應用是物理引擎中必不可少的部分,你有剛體能碰撞卻不能推動它,那麼它必定會給你帶來很強的挫敗感。
在這個教程中,主要是對剛體的幾個方法進行了應用,這些方法都很簡單易用。
剛體有兩個點對我們有用,一個是剛體的座標點,另一個是剛體的質心位置。剛體的質心位置就不需要你自己指出,Box2D將會自己算出這個座標。
剛體有如下幾個成員變量,
uint32 m_flags;
質心位置:
b2Vec2 m_position;
質心旋轉度:
float32 m_rotation;
線性速度:
b2Vec2 m_linearVelocity;
角速度:
float32 m_angularVelocity;
力:
b2Vec2 m_force;
扭矩:
float32 m_torque;


形狀表:
b2Shape* m_shapeList;
形狀數:
int32 m_shapeCount;
關節表:
b2JointNode* m_jointList;
關節數:
b2ContactNode* m_contactList;
質量:
float32 m_mass, m_invMass;
float32 m_I, m_invI;
線性阻尼:
float32 m_linearDamping;
角阻尼:
float32 m_angularDamping;
休眠時間
float32 m_sleepTime;
用戶數據:
void* m_userData;




並有以下幾種方法:
1、設置剛體位置和旋轉度
void SetOriginPosition(const b2Vec2& position, float32 rotation);


2、取剛體當前位置


b2Vec2 GetOriginPosition() const;


3、設置剛體的質心位置及旋轉度


void SetCenterPosition(const b2Vec2& position, float32 rotation);


4、取得剛體的質心位置


b2Vec2 GetCenterPosition() const;


5、取得旋轉度


float32 GetRotation() const;
6、取得旋轉矩陣


const b2Mat22& GetRotationMatrix() const;


7、設置和取得質心的線性速度
void SetLinearVelocity(const b2Vec2& v);
b2Vec2 GetLinearVelocity() const;
8、設置和取得角速度
void SetAngularVelocity(float32 w);
float32 GetAngularVelocity() const;
9、應用一個力到世界點上
void ApplyForce(const b2Vec2& force, const b2Vec2& point);
force爲力的大小,point爲作用點
10、應用一個扭矩
void ApplyTorque(float32 torque);
11、在點上應用一個推力


void ApplyImpulse(const b2Vec2& impulse, const b2Vec2& point);
12、取得質量
float32 GetMass() const;
13、取得慣性
float32 GetInertia() const;
14、取得世界點(取得給定相對於質心的點的世界座標)
b2Vec2 GetWorldPoint(const b2Vec2& localPoint);
15、根據屆出當前座標系給的向量來得到世界向量
b2Vec2 GetWorldVector(const b2Vec2& localVector);
16、根據給定世界座標來得到相對於質心的座標
b2Vec2 GetLocalPoint(const b2Vec2& worldPoint);
17、根據一個世界向量來取得一個此時的向量
b2Vec2 GetLocalVector(const b2Vec2& worldVector);
18、判斷剛體是否靜止
bool IsStatic() const;
19、判斷剛體是否冷凍
bool IsFrozen() const;
20、判斷剛體是否休眠
bool IsSleeping() const;
21、你可以用它來單獨設置這個剛體是否可以休眠
void AllowSleeping(bool flag);
22、喚醒這個剛體
void WakeUp();
23、取得附加在這個剛體上的形狀表
b2Shape* GetShapeList();
24、取得附加在這個剛體上的聯繫表
b2ContactNode* GetContactList();
25、取得附加在這個剛體上的所有關節表
b2JointNode* GetJointList();
26、取得這個剛體在世界剛體表中的下一剛體
b2Body* GetNext();
27、取得用戶數據
void* GetUserData();


void SynchronizeShapes();
void QuickSyncShapes();
// This is used to prevent connected bodies from colliding.
// It may lie, depending on the collideConnected flag.
bool IsConnected(const b2Body* other) const;
// This is called when the child shape has no proxy.
void Freeze();




標記
enum
{
e_staticFlag = 0x0001,
e_frozenFlag = 0x0002,
e_islandFlag = 0x0004,
e_sleepFlag = 0x0008,
e_allowSleepFlag = 0x0010,
e_destroyFlag = 0x0020,
};


雖然說剛體這個類的很多成員變量沒有私有化,但是還是建議你使用它的衆多方法來管理。
在進行力學應用的時候,經常會需要相關轉換座標,所以建議找找相關書看看。


六、 Web




在開始之前,我們先來回顧一下以前所討論過的形狀,剛體,在這裏我們來看看使用他們有什麼值得注意的地方。
1、關於多邊形形狀定義,我們由b2_maxPolyVertices決定了最大頂點數爲8,如果你想要更多的多邊形,那麼我可以在 b2Setting.h裏面修改相關數值。你在使用多邊形時,一定要指定頂點數,而且頂點座標得按逆時針順序(CCW),你不能交疊任何的頂點,多邊形會自動幫你閉合,同時這個多邊形得凸起的,也就是說你必須讓每個頂點都向外擴展一定角度,以上幾點很重要,不要因此引起許多莫名其妙的錯誤。
2、關於摩擦力和彈性係數,摩擦力與應力是成比例關係,它介出0和1之間,0表示無摩擦,1表示摩擦力很強,如果有兩個形狀都定義了摩擦力,那麼它實際摩擦力將會是兩個摩擦力的乘積開根。
3、彈性係數讓物體能夠彈起來,值也介於0與1之間,如果一個球掉到桌面上來,這個值是0的時候則不會彈起來,如果是1的話那麼就叫完全彈性碰撞,如果剛體中有兩個形狀都有不同的彈性係數,那麼使用這個方法:
float32 restitution;
restitution = b2Max(shape1->restitution, shape2->restitution);
4、關於碰撞過濾,有三種情況下是附加影響碰撞的,靜態物體之間形狀不發生碰撞,同一個剛體中的形狀不發生碰撞,你能設置的在關節連接的兩個物體形狀間是否發生碰撞。
5、關於創建和銷燬一個形狀,你沒有必要去討論形狀的創建和銷燬,Box2D會幫你自動完成。
6、每一剛體添加形狀是由參數b2_maxShapesPerBody來控制的,目前最大設爲64,如果你想要更大的話,那麼你修改b2Setting.h裏面相關數值。
7、關於剛體創建與銷燬,你不需要手動爲一個剛體分配和釋放內存,這些都由引擎自動完成,所以你創建的時候,你僅僅需要:
b2Body* body = myWorld->CreateBody(&bodyDef);
銷燬的時候:
myWorld->DestroyBody(body);
body = NULL;
8、當剛體被銷燬時,附加在上面的關節都會自動銷燬,你必須清空這些關節指針,不然你的程序會在你以後銷燬關卡的時候死得很難看。爲了幫助你清空你的關卡指針,Box2D提供一個叫作b2WorldListener的監聽類,你可以應用它來清空,之後世界就會告訴你到一個關節被銷燬。
9、喚醒一個休眠物體你只能用b2Body::WakeUp,在它上面應用任何力是不可以喚醒一個剛體的。
10、要擅於利用剛體的轉換函數,它會幫我們解決很多問題。
11、在Debug模式下,最好能利用下列代碼把形狀顯示出來,幫助我們調試。
for (b2Shape* s = body->GetShapeList(); s; s = s->GetNext())
{
GameDrawShape(s);
}
12、Box2D裏面所說的角度都是指弧度。
正文
在這一教程開始之前,先來討論關節。
關節(Joint)其實就是用來連接剛體的,你可以想像一下你的手。每一個關節也有一個關節定義b2JointDef,所有關節都連接在兩個不同的剛體之間,一個可能是靜態,如果你想浪費內存的話,就創建一個連在兩個靜態剛體上吧。
關節是物體引擎中的另一重要部分,所以Box2D中把它作了細分,我們目前暫時先討論在這個例程中使用的Distance關節。
先來看b2JointDef的結構:
struct b2JointDef
{


b2JointType type;
void* userData;
b2Body* body1;
b2Body* body2;
bool collideConnected;
};
Type表示爲類別e_unknownJoint、 e_revoluteJoint、e_prismaticJoint、 e_distanceJoint、 e_pulleyJoint、 e_mouseJoint、 e_gearJoint。Userdata是用戶數據,body1、body2爲兩個剛體指針,collideConnected表示是否在兩個剛體之間檢查碰撞。
Distance Joint是一種用來連接兩個剛體的有距線段關節。你使用它的時候必須分別給兩個剛體指定兩個錨點,這兩個點意味着此關節的長度。


b2DistanceJointDef的結構
struct b2DistanceJointDef : public b2JointDef
{


b2Vec2 anchorPoint1;
b2Vec2 anchorPoint2;
};
繼承於b2JointDef,只是多了兩個錨點。


下面是此關節定義的一個應用:
b2DistanceJointDef jointDef;
jointDef.body1 = myBody1;
jointDef.body2 = myBody2;
jointDef.collideConnected = true;
jointDef.anchorPoint1 = myBody1->GetCenterPosition();
jointDef.anchorPoint2 = myBody2->GetCenterPosition();




參照Web例子,我們會發現定義一個關節其實也很簡單
1、指定關節定義
2、創建關節
3、結束時銷燬關節


七、 Chain、Bridge、Cradle




Chain、Bridge兩個例程是對Revolute Joint的應用,Revolute Joint是兩個剛體共用一個錨點,它有一個自由度,在這裏被叫作關節角度。


爲了指定一個Revolute你必須提供兩個剛體和一個錨點,引擎會假定這兩個剛體已經在正確位置上。
它的結構如下:
struct b2RevoluteJointDef : public b2JointDef
{
b2Vec2 anchorPoint;
float32 lowerAngle;
float32 upperAngle;
float32 motorTorque;
float32 motorSpeed;
bool enableLimit;
bool enableMotor;
};
它也是繼承於b2JointDef,anchorPoint是錨點,lowerAngle爲轉動角底限,upperAngle爲轉動角上限,其他的這裏暫時先不介紹。
Chain、Bridge兩個例子非常簡單,和Distance Joint相差不大,算是對Joint使用的再次鞏固。
八、 Pulleys




Pulleys是對Prismatic Joint、Pulley Joint的應用,Prismatic Joint是一種允許兩個剛體沿指定軸相對移動的關節,不允許相對旋轉,所以有一個自由度。


它的結構下:
struct b2PrismaticJointDef : public b2JointDef
{
b2Vec2 anchorPoint;
b2Vec2 axis;
float32 lowerTranslation;
float32 upperTranslation;
float32 motorForce;
float32 motorSpeed;
bool enableLimit;
bool enableMotor;
};
我們這時暫時只應用到anchorPoint,axis,axis爲軸,lowerTranslation爲移動底限,upperTranslation爲移動上限,而其他幾項我們在Joint motor塊討論。
Pulley Joint用來創建理想滑輪,滑輪連接兩個剛體,一個上去,一個便下來,根據你的最初設定來決定你的繩長。
length1 + length2 ==常數C


你可以應用一個比例關係來模擬滑車裝置,這會導致一邊伸展得比另一邊快,同時約束力也是一邊大一邊小,你可以用它來創建槓桿。
length1 + ratio * length2 == 常數C
舉個例子,如果ratio(比例關係)是2,那麼length1會變成length2的兩倍,當作用在附加在剛體1上的繩上的力將會是作用在附加在剛體2上的力的一半。
struct b2PulleyJointDef : public b2JointDef
{
b2Vec2 groundPoint1;
b2Vec2 groundPoint2;
b2Vec2 anchorPoint1;
b2Vec2 anchorPoint2;
float32 maxLength1;
float32 maxLength2;
float32 ratio;
};
groundPoint1、groundPoint2是剛體1、2上面繩子的頂點,anchorPoint1、anchorPoint2是剛體與繩子連接的點,maxLength1、maxLength2爲兩剛體的最大長度,ratio是比例係數。
九、 Gears


Gears內容裏面有關於Revolute Joint、Prismatic Joint、Gear Joint的應用,前兩種已經在前面討論過,現在我們先看Gear Joint。


Gear Joint直接翻譯爲齒輪關節,顧名思義就是用來處理齒輪類物體的相互關聯。
你在使用Gear Joint的時候必須先有一個附加了Prismatic Joint(此關節連接你的剛體和你的包容盒)的剛體和一個附加了Revolute Joint(此關節連接你的剛體和你的包容盒)的剛體咬合在一起。然後再用Gear Joint把這兩個剛體連接到一起。
和Pulley Joint一樣也有ratio值,在這裏這個值可以是負數,記住我們兩必要關節一個是Revolute Joint,另一個是Prismatic Joint,所以
coordinate1 + ratio * coordinate2 == 常數C
這個例子已經應用了ratio值,你可以自己動手調調,來看看效果和作用。
Gear Joint依賴於兩個子關節,一般是在兩個子關節之前刪除,甚至於是在所有有關剛體被刪除之前刪除。
結構如下:
struct b2GearJointDef : public b2JointDef
{
b2Joint* joint1;
b2Joint* joint2;
float32 ratio;
};
繼承於關節定義, joint1、joint2表示兩個定義在剛體上面的關節,ratio表示比例關係。


十、Joint(附加)




其實上面講了那麼多種關節,但是我們都還沒有真正討論過joint,joint這裏翻譯爲關節,它的結構爲
b2JointType m_type;
b2Joint* m_prev;
b2Joint* m_next;
b2JointNode m_node1;
b2JointNode m_node2;
b2Body* m_body1;
b2Body* m_body2;


bool m_islandFlag;
bool m_collideConnected;


void* m_userData;


m_type是類型,分爲 e_unknownJoint、e_revoluteJoint、 e_prismaticJoint、e_distanceJoint、e_pulleyJoint、e_mouseJoint、e_gearJoint。指針節點這些都應用在數據結構上,定義是兩個剛體對象:m_body1、m_body2,m_collideConnected表示連接剛體之間是否碰撞,還有一個函數指針型的m_userData來存儲自己的數據。m_islandFlag這個標識暫時不用去管。


支持的方法有:
1、b2JointType GetType() const;
取得關節類型。
2、b2Body* GetBody1();
取得剛體1
3、b2Body* GetBody2();
取得剛體2
4、virtual b2Vec2 GetAnchor1() const = 0;
取得錨點1
5、virtual b2Vec2 GetAnchor2() const = 0;
取得錨點2
6、virtual b2Vec2 GetReactionForce(float32 invTimeStep) const = 0;
取得反作用力
7、virtual float32 GetReactionTorque(float32 invTimeStep) const = 0;
取得反作用扭矩
8、b2Joint* GetNext();
取得下一個關節
9、void* GetUserData();
取得用戶數據
10、static b2Joint* Create(const b2JointDef* def, b2BlockAllocator* allocator);
創建關節
11、static void Destroy(b2Joint* joint, b2BlockAllocator* allocator);
銷燬關節
12、其他方法(暫不介紹)
virtual void PrepareVelocitySolver() = 0;
virtual void SolveVelocityConstraints(const b2TimeStep* step) = 0;
virtual void PreparePositionSolver() {}
virtual bool SolvePositionConstraints() = 0;


以前所討論過的幾種關節都是繼承於b2Joint而來,下面列出了相關附加屬性和方法。不推薦直接使用相關成員變量來取值或賦值,要擅於利用相關功能函數來取值。
Gear Joint:
附加屬性(常用):
b2Body* m_ground1;
地面剛體1指針
b2Body* m_ground2;
地面剛體2指針


b2RevoluteJoint* m_revolute1;


RevoluteJoint指針1


b2PrismaticJoint* m_prismatic1;


PrismaticJoint指針1


b2RevoluteJoint* m_revolute2;


RevoluteJoint指針2


b2PrismaticJoint* m_prismatic2;


PrismaticJoint指針2




b2Vec2 m_groundAnchor1;
地面錨點1


b2Vec2 m_groundAnchor2;
地面錨點2


b2Vec2 m_localAnchor1;
當前錨點1


b2Vec2 m_localAnchor2;
當前錨點2
float32 m_ratio;
比例關係


float32 m_mass;
質量
float32 m_impulse;
推力
附加方法:
1、float32 GetRatio() const;
取得比例關係
Revolute Joint:
附加屬性:
b2Vec2 m_localAnchor1;


b2Vec2 m_localAnchor2;
b2Vec2 m_ptpImpulse;
float32 m_motorImpulse;
float32 m_limitImpulse;
float32 m_limitPositionImpulse;


b2Mat22 m_ptpMass; // effective mass for point-to-point constraint.
float32 m_motorMass; // effective mass for motor/limit angular constraint.
float32 m_intialAngle;
float32 m_lowerAngle;
float32 m_upperAngle;
float32 m_maxMotorTorque;
float32 m_motorSpeed;


bool m_enableLimit;
bool m_enableMotor;
b2LimitState m_limitState;
附加方法:


1、float32 GetJointAngle() const;
取得關節角度
2、float32 GetJointSpeed() const;
取得關節速度
3、float32 GetMotorTorque(float32 invTimeStep) const;
取得發動扭矩
4、void SetMotorSpeed(float32 speed);
取得發動速度
5、void SetMotorTorque(float32 torque);
設置發動扭矩
Prismatic Joint:
附加方法:
1、float32 GetJointTranslation() const;
取得關節位移
2、float32 GetJointSpeed() const;
取得關節速度
3、float32 GetMotorForce(float32 invTimeStep) const;
取得發動應力


4、 void SetMotorSpeed(float32 speed);
設置發動速度
5、void SetMotorForce(float32 force);
設置發動速度
Revolute Joint:
附加方法:
1、float32 GetJointAngle () const;
取得關節角度
2、float32 GetJointSpeed() const;
取得關節速度
3、float32 GetMotorTorque (float32 invTimeStep) const;
取得發動扭矩


4、 void SetMotorSpeed(float32 speed);
設置發動速度
5、void SetMotorTorque (float32 torque);
設置發動扭矩
十一、Joint motor(MotorsAndLimits、SliderCrank)




在開始之前,我們再來回顧一下Joint,我們前面討論過的情況來看,在幾種Joint中應用到motor的只有Prismatic Joint和Revolute Joint。在使用motor時總有那麼幾個常見量,float32 motorTorque或者float32 motorForce、 float32 motorSpeed、bool enableLimit、bool enableMotor。
motorTorque或motorForce表示現在的扭矩或應力,Revolute Joint就是扭矩,因爲他共用一個錨點,只能沿這錨點轉動,而Prismatic Joint支持基於軸的移動,所以他是應力。
motorSpeed表示的是把這應力或者扭距應用到剛體上的數值增減程度。(僅當參考,事實是你加大減少這個值會讓遊戲數值瞬間變化量變多或變少,理解就行)
enableMotor是決定使用不使用Motor。
enableLimit決定上下限(角度或者長度)是否有用。
在SliderCrank這個例子中,先是定義了一個剛體,並用這個剛體和地面創建了一個Revolute Joint,這個Revolute Joint的motorTorque值設爲一定值,讓這個剛體持續轉動,當然你的速度越快,轉動就越快。這個剛體又用Revolute Joint連接了一個剛體,但這個Revolute Joint無效了motor,所以這個剛體只能靠其他剛體讓他移動。又用Revolute Joint連接了活塞剛體,同樣是無效了motor,之後創建了Prismatic Joint來連接你的活塞和地面,給定了應力,所以這個應力就使得上面掉下來的塊上升。
注意他的相關座標設置。
總結一下,這裏真正提供動力的有兩個東西,一個是活塞,他是給下面掉下來的塊提供力量,另一個是最持續轉動的剛體盒子,他供給活塞以及他上面的塊能量。
MotorsAndLimits這個例子同樣很好理解,除了對motor的應用外,還使用了enableLimit值,這個值是用來做什麼,上面說過了,是用來決定在JointDef中定義的相關上下限是否起效。
試着改動相關數據對你理解更有效。
十二、CollisionProcessing




CollisionProcessing這個例子是有關於Contacts的使用。這個東西是Box2D用來在形狀間檢測碰撞的,有很多不同種類的 Contacts,比如說負責圓和圓碰撞的,負責圓和多邊形碰撞的。這些其實你都沒有必要去了解它,你只要會應用你最需要的就行了。
這裏你最起碼需要了解的幾個概念:
Contact:就是用來管理碰撞的
contact manifold:這個東西就是碰撞時候產生的,是一個由碰撞點組成的矢量線段。
contact point:碰撞點


在例子CollisionProcessing中的Step部分,先從世界的Contacts表裏取出你需要的連接,然後取得contact manifold的數量,如果有連接,然後再做出相應的處理。
b2Contact的結構:
重要的屬性:
發生碰撞的兩個形狀
b2Shape* m_shape1;


b2Shape* m_shape2;
contact manifold的數量
int32 m_manifoldCount;
組合摩擦力和彈性係數
float32 m_friction;
float32 m_restitution;
重要的成員函數:
取得相應的contact manifold
virtual b2Manifold* GetManifolds() = 0;
取得contact manifold數
int32 GetManifoldCount() const
取得下一個Contact
b2Contact* GetNext();
取得這個Contact的兩個形狀
b2Shape* GetShape1();


b2Shape* GetShape2();

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章