我張貼在這裏,因爲我還沒有直接的子彈物理論壇或任何其要麼這些相關的論壇找到一個有用的答案已經成功移植庫[JBullet,BulletCS]或將其併入自己的產品[Blender,Panda3d]。在這裏看來,至少如果我能夠正確地提出這個問題的話,似乎最好的方式是獲得有用的答覆。子彈物理MultiSphereShape使用
我想模擬骰子的滾動。我能找到的所有例子似乎都與使用Box形狀有關。我對兒童遊戲感興趣,而不是拉斯維加斯。至少在我的應用中,至少在我的應用中,定義的區別是骰子[無論是6面,還是其他的,但是我們只是堅持6面],它們有'更溫和'圓潤的邊緣,沒有尖角。
看來btMultiSphereShape對我來說是完美的 - 我是一個沒有從低級基元構造任何複雜形狀的知識的人,我是一個希望使用已經內置到Bullet引擎的碰撞智能,而不是有人試圖設計任何新的,奇特的行爲。
隨着序言中我會很感激的一個簡潔的例子:
一個。如何將參數傳遞給btMultiSphhereShape構造函數; b。如何配置需要傳遞給btDefaultMaotionState的轉換;和 c。如何設置localInertia。
我知道這是一個通用庫,它的類可以支持幾乎所有的類,但對於初學者來說,請不要討論構思良好的工具包的非常好的屬性,最有幫助的是什麼對我來說[我相信許多其他用戶]將是一個明確的例子,將這些關鍵屬性提供給這些細節所需的類別和方法:
a。一個尺寸相同的六面骰子,讓我們製作一個圓角立方體,每邊大約2釐米; b。讓我們將「角落」的半徑設爲0.1.cm。
現在,請再提一個請求。爲了以簡單的「下落」開始觀察模具的行爲,只考慮由於重力引起的力,請建議進行轉換,這將導致與通常的「樓層」示例發生碰撞時產生某種有趣的翻滾結果;換句話說,它應該在圓角上撞擊地板。
1
A
回答
1
我在iOS設備上使用Bullet Physics創建了一個骰子游戲。爲了獲得更逼真的骰子,我創建了一個「RoundedCube」對象,它只是一個帶有斜邊的立方體。這是我寫的創建verticies
//
// Created by John Carter on 4/9/09.
//
#import "RoundedCube.h"
static const GLfloat voffset[] =
{
// Front Face (counterclockwise winding)
+1.0f, +1.0f, +1.0f,
-1.0f, +1.0f, +1.0f,
-1.0f, -1.0f, +1.0f,
+1.0f, +1.0f, +1.0f,
-1.0f, -1.0f, +1.0f,
+1.0f, -1.0f, +1.0f,
// Back Face (clockwise winding)
+1.0f, +1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, +1.0f, -1.0f,
+1.0f, +1.0f, -1.0f,
+1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
// Top Face (counterclockwise winding)
-1.0f, +1.0f, +1.0f,
+1.0f, +1.0f, -1.0f,
-1.0f, +1.0f, -1.0f,
-1.0f, +1.0f, +1.0f,
+1.0f, +1.0f, +1.0f,
+1.0f, +1.0f, -1.0f,
// Bottom Face (clockwise winding)
-1.0f, -1.0f, +1.0f,
-1.0f, -1.0f, -1.0f,
+1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, +1.0f,
+1.0f, -1.0f, -1.0f,
+1.0f, -1.0f, +1.0f,
// Right Face (clockwise winding)
+1.0f, -1.0f, +1.0f,
+1.0f, +1.0f, -1.0f,
+1.0f, +1.0f, +1.0f,
+1.0f, -1.0f, +1.0f,
+1.0f, -1.0f, -1.0f,
+1.0f, +1.0f, -1.0f,
// Left Face (counterclockwise winding)
-1.0f, -1.0f, +1.0f,
-1.0f, +1.0f, +1.0f,
-1.0f, +1.0f, -1.0f,
-1.0f, +1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, +1.0f,
};
// Private Methods
//
@interface RoundedCube()
- (void) computeRoundedCubeNormals;
@end
@implementation RoundedCube
- (void) dealloc
{
[super dealloc];
}
- (void) computeRoundedCubeNormals
{
int i;
xMinVertex = FLT_MAX;
yMinVertex = FLT_MAX;
zMinVertex = FLT_MAX;
xMaxVertex = -FLT_MAX;
yMaxVertex = -FLT_MAX;
zMaxVertex = -FLT_MAX;
for (i=0; i<vertexDataCount; i+=3)
{
if (vertexData[i+0] < xMinVertex)
xMinVertex = vertexData[i+0] ;
if (vertexData[i+1] < yMinVertex)
yMinVertex = vertexData[i+1] ;
if (vertexData[i+2] < zMinVertex)
zMinVertex = vertexData[i+2] ;
if (vertexData[i+0] > xMaxVertex)
xMaxVertex = vertexData[i+0] ;
if (vertexData[i+1] > yMaxVertex)
yMaxVertex = vertexData[i+1] ;
if (vertexData[i+2] > zMaxVertex)
zMaxVertex = vertexData[i+2] ;
}
xVertexRange = fabs(xMaxVertex - xMinVertex);
yVertexRange = fabs(yMaxVertex - yMinVertex);
zVertexRange = fabs(zMaxVertex - zMinVertex);
for (i=0; i<vertexDataCount; i+=9)
{
btVector3 V0 = btVector3(vertexData[i+0], vertexData[i+1], vertexData[i+2]);
btVector3 V1 = btVector3(vertexData[i+3], vertexData[i+4], vertexData[i+5]);
btVector3 V2 = btVector3(vertexData[i+6], vertexData[i+7], vertexData[i+8]);
btVector3 delta1 = (V1) - (V0);
btVector3 delta2 = (V2) - (V0);
btVector3 vertexNormal = delta1.cross(delta2);
vertexNormal = vertexNormal.normalize();
if (useAbsNormals)
{
vertexNormal = vertexNormal.absolute();
}
normalData[i+0] = vertexNormal[0];
normalData[i+1] = vertexNormal[1];
normalData[i+2] = vertexNormal[2];
normalData[i+3] = vertexNormal[0];
normalData[i+4] = vertexNormal[1];
normalData[i+5] = vertexNormal[2];
normalData[i+6] = vertexNormal[0];
normalData[i+7] = vertexNormal[1];
normalData[i+8] = vertexNormal[2];
}
}
- (void) addBeveledCorner:(int)bevelPlane At:(btVector3)bevelLocation Size:(btVector3)bevelSize Rotation:(double)rotationOrigin
{
btVector3 vertexPoint[6];
double delta;
double theta0;
double theta1;
double phi0;
double phi1;
int vp;
int i;
int j;
int k;
delta = (double)M_PI_2/(double)smoothFactor;
// vertical segments
//
for(i=0; i<smoothFactor; i++)
{
theta0 = (double)i * (double)delta;
theta1 = (double)(i+1) * (double)delta;
if (bevelPlane==1)
{
theta0 += M_PI;
theta1 += M_PI;
}
// horizontal segments
//
for(j=0; j<smoothFactor; j++)
{
phi0 = (double)j * (double)delta;
phi1 = (double)(j+1) * (double)delta;
phi0 += rotationOrigin;
phi1 += rotationOrigin;
if (bevelPlane==1)
{
phi0 += M_PI;
phi1 += M_PI;
}
vp=0;
if (bevelPlane==0)
{
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta0)*cos(phi0)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta0)), bevelLocation[2]+bevelSize[2]*btScalar(sin(theta0)*sin(phi0)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta0)*cos(phi1)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta0)), bevelLocation[2]+bevelSize[2]*btScalar(sin(theta0)*sin(phi1)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta1)*cos(phi1)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta1)), bevelLocation[2]+bevelSize[2]*btScalar(sin(theta1)*sin(phi1)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta0)*cos(phi0)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta0)), bevelLocation[2]+bevelSize[2]*btScalar(sin(theta0)*sin(phi0)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta1)*cos(phi1)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta1)), bevelLocation[2]+bevelSize[2]*btScalar(sin(theta1)*sin(phi1)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta1)*cos(phi0)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta1)), bevelLocation[2]+bevelSize[2]*btScalar(sin(theta1)*sin(phi0)));
}
else
{
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta0)*cos(phi0)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta0)), bevelLocation[2]+bevelSize[2]*btScalar(sin(theta0)*sin(phi0)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta1)*cos(phi1)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta1)), bevelLocation[2]+bevelSize[2]*btScalar(sin(theta1)*sin(phi1)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta0)*cos(phi1)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta0)), bevelLocation[2]+bevelSize[2]*btScalar(sin(theta0)*sin(phi1)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta0)*cos(phi0)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta0)), bevelLocation[2]+bevelSize[2]*btScalar(sin(theta0)*sin(phi0)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta1)*cos(phi0)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta1)), bevelLocation[2]+bevelSize[2]*btScalar(sin(theta1)*sin(phi0)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta1)*cos(phi1)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta1)), bevelLocation[2]+bevelSize[2]*btScalar(sin(theta1)*sin(phi1)));
}
for (k=0; k<6; k++)
{
vertexData[coordinateElement++] = vertexPoint[k][0];
vertexData[coordinateElement++] = vertexPoint[k][1];
vertexData[coordinateElement++] = vertexPoint[k][2];
colorData[colorElement++] = rgba[0];
colorData[colorElement++] = rgba[1];
colorData[colorElement++] = rgba[2];
colorData[colorElement++] = rgba[3];
}
}
}
}
- (void) addBeveledEdge:(int)bevelPlane At:(btVector3)bevelLocation Size:(btVector3)bevelSize Rotation:(double)rotationOrigin
{
btVector3 vertexPoint[6];
double origin;
double delta;
double theta0;
double theta1;
int vp;
int i;
int j;
delta = (double)(M_PI_2)/(double)smoothFactor;
for (i=0; i<smoothFactor; i++)
{
theta0 = (double)i * (double)delta;
theta1 = (double)(i+1) * (double)delta;
theta0 += rotationOrigin;
theta1 += rotationOrigin;
origin = (double)0.0;
vp=0;
switch(bevelPlane)
{
case 0:
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0], bevelLocation[1]+bevelSize[1]*btScalar(sin(theta0+origin)), bevelLocation[2]+bevelSize[2]*btScalar(cos(theta0+origin)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0], bevelLocation[1]+bevelSize[1]*btScalar(sin(theta1+origin)), bevelLocation[2]+bevelSize[2]*btScalar(cos(theta1+origin)));
vertexPoint[vp++] = btVector3(bevelLocation[0]-bevelSize[0], bevelLocation[1]+bevelSize[1]*btScalar(sin(theta1+origin)), bevelLocation[2]+bevelSize[2]*btScalar(cos(theta1+origin)));
vertexPoint[vp++] = btVector3(bevelLocation[0]-bevelSize[0], bevelLocation[1]+bevelSize[1]*btScalar(sin(theta0+origin)), bevelLocation[2]+bevelSize[2]*btScalar(cos(theta0+origin)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0], bevelLocation[1]+bevelSize[1]*btScalar(sin(theta0+origin)), bevelLocation[2]+bevelSize[2]*btScalar(cos(theta0+origin)));
vertexPoint[vp++] = btVector3(bevelLocation[0]-bevelSize[0], bevelLocation[1]+bevelSize[1]*btScalar(sin(theta1+origin)), bevelLocation[2]+bevelSize[2]*btScalar(cos(theta1+origin)));
break;
case 1:
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta0+origin)), bevelLocation[1]+bevelSize[1], bevelLocation[2]+bevelSize[2]*btScalar(cos(theta0+origin)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta1+origin)), bevelLocation[1]-bevelSize[1], bevelLocation[2]+bevelSize[2]*btScalar(cos(theta1+origin)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta1+origin)), bevelLocation[1]+bevelSize[1], bevelLocation[2]+bevelSize[2]*btScalar(cos(theta1+origin)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta0+origin)), bevelLocation[1]-bevelSize[1], bevelLocation[2]+bevelSize[2]*btScalar(cos(theta0+origin)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta1+origin)), bevelLocation[1]-bevelSize[1], bevelLocation[2]+bevelSize[2]*btScalar(cos(theta1+origin)));
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta0+origin)), bevelLocation[1]+bevelSize[1], bevelLocation[2]+bevelSize[2]*btScalar(cos(theta0+origin)));
break;
case 2:
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta0+origin)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta0+origin)), bevelLocation[2]+bevelSize[2]);
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta1+origin)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta1+origin)), bevelLocation[2]+bevelSize[2]);
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta1+origin)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta1+origin)), bevelLocation[2]-bevelSize[2]);
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta0+origin)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta0+origin)), bevelLocation[2]-bevelSize[2]);
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta0+origin)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta0+origin)), bevelLocation[2]+bevelSize[2]);
vertexPoint[vp++] = btVector3(bevelLocation[0]+bevelSize[0]*btScalar(sin(theta1+origin)), bevelLocation[1]+bevelSize[1]*btScalar(cos(theta1+origin)), bevelLocation[2]-bevelSize[2]);
break;
}
for (j=0; j<6; j++)
{
vertexData[coordinateElement++] = vertexPoint[j][0];
vertexData[coordinateElement++] = vertexPoint[j][1];
vertexData[coordinateElement++] = vertexPoint[j][2];
colorData[colorElement++] = rgba[0];
colorData[colorElement++] = rgba[1];
colorData[colorElement++] = rgba[2];
colorData[colorElement++] = rgba[3];
}
}
}
- (RoundedCube *) Length:(GLfloat)initLength Width:(GLfloat)initWidth Height:(GLfloat)initHeight Bevel:(GLfloat)initBevel SmoothFactor:(int)initSmoothFactor RGBA:(GLubyte *)initRGBA AbsNormals:(BOOL)initUseAbsNormals
{
int i;
smoothFactor = initSmoothFactor;
useAbsNormals = initUseAbsNormals;
shape = (id *)self;
length = initLength;
width = initWidth;
height = initHeight;
bevel = initBevel;
coordinateElement=0;
colorElement=0;
for (i=0; i<24; i++)
rgba[i] = initRGBA[i];
vertexCount = 36 + (12 * 6 * smoothFactor) + (smoothFactor * smoothFactor * 6 * 8);
modelType = MT_BOX;
constructMode = GL_TRIANGLES;
showColorAndTexture = NO;
vertexDataCount = vertexCount * 3;
colorDataCount = vertexCount * 4;
normalDataCount = vertexCount * 3;
[self setSurfaceToDefault];
vertexData = (GLfloat *)malloc(sizeof(GLfloat) * vertexDataCount);
memset(vertexData, (unsigned int)0, sizeof(GLfloat) * vertexDataCount);
normalData = (GLfloat *)malloc(sizeof(GLfloat) * normalDataCount);
memset(normalData, (unsigned int)0, sizeof(GLfloat) * normalDataCount);
colorData = (GLubyte *)malloc(sizeof(GLubyte) * colorDataCount);
memset(colorData, (unsigned int)0, sizeof(GLubyte) * colorDataCount);
int cubeSide;
int trianglesPerSide;
int pointsPerTriangle;
for (cubeSide=0; cubeSide<6; cubeSide++)
{
for (trianglesPerSide=0; trianglesPerSide<2; trianglesPerSide++)
{
for (pointsPerTriangle=0; pointsPerTriangle<3; pointsPerTriangle++)
{
switch(cubeSide)
{
case 0:
case 1:
vertexData[coordinateElement+0] = voffset[coordinateElement+0] * (length - bevel);
vertexData[coordinateElement+1] = voffset[coordinateElement+1] * (width - bevel);
vertexData[coordinateElement+2] = voffset[coordinateElement+2] * height;
break;
case 2:
case 3:
vertexData[coordinateElement+0] = voffset[coordinateElement+0] * (length - bevel);
vertexData[coordinateElement+1] = voffset[coordinateElement+1] * width;
vertexData[coordinateElement+2] = voffset[coordinateElement+2] * (height - bevel);
break;
case 4:
case 5:
vertexData[coordinateElement+0] = voffset[coordinateElement+0] * length;
vertexData[coordinateElement+1] = voffset[coordinateElement+1] * (width - bevel);
vertexData[coordinateElement+2] = voffset[coordinateElement+2] * (height - bevel);
break;
}
coordinateElement += 3;
colorData[colorElement++] = rgba[(cubeSide*4) + 0]; // 1 RGBA color set per side
colorData[colorElement++] = rgba[(cubeSide*4) + 1]; // 1 RGBA color set per side
colorData[colorElement++] = rgba[(cubeSide*4) + 2]; // 1 RGBA color set per side
colorData[colorElement++] = rgba[(cubeSide*4) + 3]; // 1 RGBA color set per side
}
}
}
[self addBeveledEdge:2 At:btVector3((length-bevel), (width-bevel), 0) Size:btVector3(bevel,bevel,height-bevel) Rotation:(double)0.0];
[self addBeveledEdge:2 At:btVector3(-(length-bevel), (width-bevel), 0) Size:btVector3(bevel,bevel,height-bevel) Rotation:(double)-M_PI_2];
[self addBeveledEdge:2 At:btVector3(-(length-bevel), -(width-bevel), 0) Size:btVector3(bevel,bevel,height-bevel) Rotation:(double)-M_PI];
[self addBeveledEdge:2 At:btVector3((length-bevel), -(width-bevel), 0) Size:btVector3(bevel,bevel,height-bevel) Rotation:(double)M_PI_2];
[self addBeveledEdge:1 At:btVector3((length-bevel), 0, (height-bevel)) Size:btVector3(bevel,width-bevel,bevel) Rotation:(double)0.0];
[self addBeveledEdge:1 At:btVector3(-(length-bevel), 0, (height-bevel)) Size:btVector3(bevel,width-bevel,bevel) Rotation:(double)-M_PI_2];
[self addBeveledEdge:1 At:btVector3(-(length-bevel), 0, -(height-bevel)) Size:btVector3(bevel,width-bevel,bevel) Rotation:(double)-M_PI];
[self addBeveledEdge:1 At:btVector3((length-bevel), 0, -(height-bevel)) Size:btVector3(bevel,width-bevel,bevel) Rotation:(double)M_PI_2];
[self addBeveledEdge:0 At:btVector3(0, (width-bevel), (height-bevel)) Size:btVector3(length-bevel,bevel,bevel) Rotation:(double)0.0];
[self addBeveledEdge:0 At:btVector3(0, -(width-bevel), (height-bevel)) Size:btVector3(length-bevel,bevel,bevel) Rotation:(double)-M_PI_2];
[self addBeveledEdge:0 At:btVector3(0, -(width-bevel), -(height-bevel)) Size:btVector3(length-bevel,bevel,bevel) Rotation:(double)-M_PI];
[self addBeveledEdge:0 At:btVector3(0, (width-bevel), -(height-bevel)) Size:btVector3(length-bevel,bevel,bevel) Rotation:(double)M_PI_2];
[self addBeveledCorner:0 At:btVector3((length-bevel), (width-bevel), (height-bevel)) Size:btVector3(bevel,bevel,bevel) Rotation:(double)0.0];
[self addBeveledCorner:0 At:btVector3((length-bevel), (width-bevel), -(height-bevel)) Size:btVector3(bevel,bevel,bevel) Rotation:(double)-M_PI_2];
[self addBeveledCorner:0 At:btVector3(-(length-bevel), (width-bevel), (height-bevel)) Size:btVector3(bevel,bevel,bevel) Rotation:(double)M_PI_2];
[self addBeveledCorner:0 At:btVector3(-(length-bevel), (width-bevel), -(height-bevel)) Size:btVector3(bevel,bevel,bevel) Rotation:(double)M_PI];
[self addBeveledCorner:1 At:btVector3((length-bevel), -(width-bevel), (height-bevel)) Size:btVector3(bevel,bevel,bevel) Rotation:(double)0.0];
[self addBeveledCorner:1 At:btVector3((length-bevel), -(width-bevel), -(height-bevel)) Size:btVector3(bevel,bevel,bevel) Rotation:(double)-M_PI_2];
[self addBeveledCorner:1 At:btVector3(-(length-bevel), -(width-bevel), (height-bevel)) Size:btVector3(bevel,bevel,bevel) Rotation:(double)M_PI_2];
[self addBeveledCorner:1 At:btVector3(-(length-bevel), -(width-bevel), -(height-bevel)) Size:btVector3(bevel,bevel,bevel) Rotation:(double)M_PI];
[self computeRoundedCubeNormals];
return self;
}
@end在Objective-C代碼
如果你有一個iOS設備就可以看到了它在我的免費應用程序的例子Amazing Dice HD on iTunes
1
我已經從我的一些舊項目中發佈了另一塊代碼,可能會讓您朝着正確的方向前進。我也添加了所有的依賴關係,所以它很多。可以幫助的方法是MeshObject,我基本上採取了模型的頂點,以創建相應的子彈對象增加了物理世界
//
// BulletEngine.h
// Created by John Carter on 4/9/09.
//
#import <Foundation/Foundation.h>
#include "btBulletDynamicsCommon.h"
#include "Matrix.h"
@interface BulletEngine : NSObject
{
btScalar cycles; // number of clocktick cycles to run with each call
btScalar clockTick; // 0.016 = 1/60th of a second
}
@property (readwrite) btScalar cycles;
@property (readwrite) btScalar clockTick;
- (void) timeStep:(UIAccelerationValue *)accelerationValue;
- (void) timeStep;
- (void) addConstraint:(btTypedConstraint *)hinge disableCollisionsBetweenLinkedBodies:(BOOL)linkcrash;
- (void) releaseConstraints;
@end
//
// BulletEngine.m
// Created by John Carter on 4/9/09.
//
#import "BulletEngine.h"
#import "PhysicsObject.h"
// Private Methods
//
@interface BulletEngine()
@end
@implementation BulletEngine
@synthesize cycles;
@synthesize clockTick;
static btCollisionConfiguration* sCollisionConfig=0;
static btCollisionDispatcher* sCollisionDispatcher=0;
static btSequentialImpulseConstraintSolver* sConstraintSolver=0;
static btBroadphaseInterface* sBroadphase=0;
static btDiscreteDynamicsWorld *sDynamicsWorld=0;
- (id)init
{
self = [super init];
if (self==nil)
return self;
// init Default Timing
//
cycles = 2;
clockTick = 0.016;
// init Bullet Objects
//
sCollisionConfig = new btDefaultCollisionConfiguration();
sCollisionDispatcher = new btCollisionDispatcher(sCollisionConfig);
sConstraintSolver = new btSequentialImpulseConstraintSolver;
sBroadphase = new btDbvtBroadphase();
sDynamicsWorld = new btDiscreteDynamicsWorld(sCollisionDispatcher,sBroadphase,sConstraintSolver,sCollisionConfig);
sDynamicsWorld->setGravity(btVector3(0.0f,0.0f,0.0f)); // Initial Gravity of the object Space
[PhysicsObject setDynamicsWorldPointerTo:sDynamicsWorld];
//
// 2.75 Increased performance by disabling motion state synchronization for static/inactive objects.
// if that causes a problem. Uncomment the next line for backward compatibility.
//
// sDynamicsWorld->setSynchronizeAllMotionStates(true);
return self;
}
- (void)dealloc
{
[self releaseConstraints];
delete sDynamicsWorld;
sDynamicsWorld=0;
delete sConstraintSolver;
sConstraintSolver=0;
delete sCollisionDispatcher;
sCollisionDispatcher=0;
delete sBroadphase;
sBroadphase=0;
delete sCollisionConfig;
sCollisionConfig=0;
[super dealloc];
}
- (void) releaseConstraints
{
int i;
// remove contraints
//
for (i=sDynamicsWorld->getNumConstraints()-1; i>=0; i--)
{
btTypedConstraint *joint = sDynamicsWorld->getConstraint(i);
sDynamicsWorld->removeConstraint(joint);
delete joint;
}
}
- (void) addConstraint:(btTypedConstraint *)hinge disableCollisionsBetweenLinkedBodies:(BOOL)linkcrash
{
if (linkcrash)
sDynamicsWorld->addConstraint(hinge, true);
else
sDynamicsWorld->addConstraint(hinge, false);
}
- (void) timeStep:(UIAccelerationValue *)accelerationValue;
{
if (!sDynamicsWorld)
return;
sDynamicsWorld->setGravity(btVector3(accelerationValue[0], accelerationValue[1], accelerationValue[2]));
// Recommended values for faster systems or more simple Open/GL projects
//
// cycles = 1;
// clockTick = 0.016f;
//
sDynamicsWorld->stepSimulation(cycles*clockTick, cycles, clockTick);
}
//
// Same as above but with NO Gravity
//
- (void) timeStep
{
if (!sDynamicsWorld)
return;
sDynamicsWorld->stepSimulation(cycles*clockTick, cycles, clockTick);
}
@end
//
// PhysicsObject.h
// Created by John Carter on 4/9/09.
//
#import "BulletEngine.h"
@interface PhysicsObject : NSObject
{
btCollisionShape* collisionShape;
btRigidBody *rigidBody;
btDefaultMotionState *motionState;
btCollisionObject *collisionObject;
}
@property (readonly) btCollisionShape* collisionShape;
@property (readonly) btRigidBody *rigidBody;
@property (readonly) btDefaultMotionState *motionState;
@property (readonly) btCollisionObject *collisionObject;
+ (void) setDynamicsWorldPointerTo:(btDiscreteDynamicsWorld *)initSDynamicsWorld;
- (btRigidBody *) addPhysicsObject:(btCollisionShape *)newObjectShape At:(btVector3)location Tilt:(btVector3)tilt Mass:(btScalar)mass;
- (btRigidBody *) addInfinitePlane:(int)plane Shape:(btBoxShape *)worldBoxShape At:(btTransform)groundTransform Boundary:(btVector3)boundarySize;
@end
//
// PhysicsObject.m
// Created by John Carter on 4/9/09.
//
#import "PhysicsObject.h"
// Owned and Set by BulletEngine Object
//
static btDiscreteDynamicsWorld *sDynamicsWorld;
// Private Methods
//
@interface PhysicsObject()
@end
@implementation PhysicsObject
@synthesize collisionShape;
@synthesize rigidBody;
@synthesize motionState;
@synthesize collisionObject;
+ (void) setDynamicsWorldPointerTo:(btDiscreteDynamicsWorld *)initSDynamicsWorld
{
sDynamicsWorld=initSDynamicsWorld;
}
- (void)dealloc
{
if (collisionShape)
{
delete collisionShape;
collisionShape = 0;
}
if (rigidBody)
{
sDynamicsWorld->removeRigidBody(rigidBody);
}
if (motionState)
{
delete motionState;
motionState = 0;
}
if (collisionObject)
{
sDynamicsWorld->removeCollisionObject(collisionObject);
delete collisionObject;
collisionObject = 0;
}
if (rigidBody)
{
delete rigidBody;
rigidBody = 0;
}
[super dealloc];
}
- (void) setCollisionObjectPointer
{
int i;
for (i=sDynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
{
btCollisionObject* colObj = sDynamicsWorld->getCollisionObjectArray()[i];
if (colObj)
{
btRigidBody* body = btRigidBody::upcast(colObj);
if (body==rigidBody)
{
collisionObject = colObj;
return;
}
}
}
collisionObject=0;
return;
}
- (btRigidBody *) addInfinitePlane:(int)plane Shape:(btBoxShape *)worldBoxShape At:(btTransform)groundTransform Boundary:(btVector3)boundarySize
{
btVector4 planeEq;
worldBoxShape->getPlaneEquation(planeEq, plane);
collisionShape = new btStaticPlaneShape(-planeEq, planeEq[3]);
motionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(btScalar(0.0), motionState, collisionShape, btVector3(btScalar(0.0),btScalar(0.0),btScalar(0.0)));
btRigidBody* objectBody = new btRigidBody(rbInfo);
sDynamicsWorld->addRigidBody(objectBody);
[self setCollisionObjectPointer];
return objectBody;
}
- (btRigidBody *) addPhysicsObject:(btCollisionShape *)newObjectShape At:(btVector3)location Tilt:(btVector3)tilt Mass:(btScalar)mass
{
btTransform bodyTransform;
bodyTransform.setIdentity();
bodyTransform.setOrigin(location);
bodyTransform.getBasis().setEulerZYX(tilt[0],tilt[1],tilt[2]);
btVector3 localInertia(0,0,0);
if (mass > btScalar(0.0))
{
newObjectShape->calculateLocalInertia(mass,localInertia);
}
motionState = new btDefaultMotionState(bodyTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,motionState,newObjectShape,localInertia);
btRigidBody* objectBody=new btRigidBody(rbInfo);
//
// Prevents objects from falling asleep after being idle for a long time
//
if (objectBody != nil && mass >= btScalar(0.0))
{
objectBody->setDeactivationTime(0.0);
objectBody->setSleepingThresholds(0.0, 0.0);
objectBody->activate();
}
//add the body to the dynamics world
//
sDynamicsWorld->addRigidBody(objectBody);
[self setCollisionObjectPointer];
return objectBody;
}
@end
//
// MeshObject.h
// Created by John Carter on 4/9/09.
//
#import "PhysicsObject.h"
@interface MeshObject : PhysicsObject
{
btTriangleMesh *mesh;
}
- (id) initAt:(btVector3)location Size:(btVector3)size VertexCount:(int)initVertexCount Verticies:(btVector3 *)initVertex Mass:(btScalar)mass;
- (id) initAt:(btVector3)location Size:(btVector3)size VertexCount:(int)initVertexCount Verticies:(btVector3 *)initVertex Tilt:(btVector3)tilt Mass:(btScalar)mass;
@end
//
// MeshObject.m
// Created by John Carter on 4/9/09.
//
#import "MeshObject.h"
// Private Methods
//
@interface MeshObject()
@end
@implementation MeshObject
- (void)dealloc
{
delete mesh;
mesh=0;
[super dealloc];
}
- (id) initAt:(btVector3)location Size:(btVector3)size VertexCount:(int)initVertexCount Verticies:(btVector3 *)initVertex Mass:(btScalar)mass
{
self = [super init];
if (self==nil)
return self;
mesh = new btTriangleMesh(false);
int i;
for (i=0 ; i<initVertexCount; i+=3)
{
btVector3 v1 = btVector3(initVertex[i+0][0]*size[0], initVertex[i+0][1]*size[1], initVertex[i+0][2]*size[2]);
btVector3 v2 = btVector3(initVertex[i+1][0]*size[0], initVertex[i+1][1]*size[1], initVertex[i+1][2]*size[2]);
btVector3 v3 = btVector3(initVertex[i+2][0]*size[0], initVertex[i+2][1]*size[1], initVertex[i+2][2]*size[2]);
mesh->addTriangle(v1,v2,v3);
}
collisionShape = new btBvhTriangleMeshShape(mesh, true);
rigidBody = [self addPhysicsObject:(btCollisionShape *)collisionShape At:(btVector3)location Tilt:btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0)) Mass:(btScalar)mass];
return self;
}
- (id) initAt:(btVector3)location Size:(btVector3)size VertexCount:(int)initVertexCount Verticies:(btVector3 *)initVertex Tilt:(btVector3)tilt Mass:(btScalar)mass
{
self = [super init];
if (self==nil)
return self;
mesh = new btTriangleMesh(false);
int i;
for (i=0 ; i<initVertexCount; i+=3)
{
btVector3 v1 = btVector3(initVertex[i+0][0]*size[0], initVertex[i+0][1]*size[1], initVertex[i+0][2]*size[2]);
btVector3 v2 = btVector3(initVertex[i+1][0]*size[0], initVertex[i+1][1]*size[1], initVertex[i+1][2]*size[2]);
btVector3 v3 = btVector3(initVertex[i+2][0]*size[0], initVertex[i+2][1]*size[1], initVertex[i+2][2]*size[2]);
mesh->addTriangle(v1,v2,v3);
}
collisionShape = new btBvhTriangleMeshShape(mesh, true);
rigidBody = [self addPhysicsObject:(btCollisionShape *)collisionShape At:(btVector3)location Tilt:tilt Mass:(btScalar)mass];
return self;
}
@end
相關問題
- 1. 子彈物理與OpenGL
- 2. 子彈物理問題
- 3. iPhone射擊遊戲子彈物理!
- 4. 我將如何使用子彈物理庫建立碰撞?
- 5. 物理角度反彈as3
- 6. 防止碰撞在子彈物理中應用衝量
- 7. 如何將旋轉應用於子彈物理引擎中的物體?
- 8. 從子彈物理四元數轉換爲與CATransform3DMakeRotation一起使用的角度
- 9. 一個簡單的方法來使用子彈物理實現尋路 - iPhone SDK
- 10. Javascript彈簧物理:將方向矢量應用於彈簧
- 11. 子彈物理學:凹形移動形狀
- 12. 增強現實+子彈物理 - RayTest/Ray採摘困難
- 13. 從文件中加載子彈物理網格
- 14. 如何在GPU上運行子彈物理解決方案
- 15. 如何模擬子彈物理引擎中的傳送帶?
- 16. 如何繪製/渲染子彈物理碰撞體/形狀?
- 17. 子彈物理 - 拾取後對象穩定
- 18. 子彈運動物理和數學到Java(Javafx)
- 19. 子彈物理目標速度(python界面)
- 20. 子彈物理最簡單的碰撞示例
- 21. 子彈物理引擎靜態庫的安裝問題
- 22. 子彈物理引擎:爲什麼重力不加速?
- 23. 如何在子彈物理中設置柔體的位置
- 24. 智能手機上的子彈物理? (Android/iPhone)
- 25. 重力物理,避免無限反彈?
- 26. 處理拋射物遺漏和彈道
- 27. 落沙粒子物理
- 28. iOS的沙子物理學
- 29. C#反彈/丟棄物品物理丟棄
- 30. Java反彈物理學:永無止境的反彈
非常感謝你約翰張貼完整的,而不是snippited代碼,它使事情更加清晰。 –
非常感謝John發佈完整的代碼,而不是吝嗇的代碼,這讓事情變得更加清晰。也就是說,我認爲你的美麗外形(我無法使用IOS設備)是一種改進的視覺對象。你的RoundedCube類如何與Bullet類集成?你的類的一個實例是否被傳遞給某個RigidBody的構造函數?你能告訴我你的骰子是如何變得質量,慣性,緊張,運動 - 與物理世界相互作用需要什麼? –
這聽起來不像你使用過Bullet。他們有一個奇妙的例子,你可以編譯,將回答你的所有問題 –