我在这里发帖是因为我没有成功地直接在Bullet物理论坛上找到一个有用的答案,或者任何那些已经移植了库[JBullet,BulletCS]或将其纳入其中的相关论坛自己的产品[Blender,Panda3d]。在这看来,至少如果我能正确地提出这个问题,似乎最好得到一个有用的答复。
我想模拟骰子的滚动。我能找到的所有例子似乎都满足于使用Box形状。我对儿童游戏很感兴趣,而不是拉斯维加斯。至少在我的应用程序中,定义的差异是骰子[无论是6面还是其他东西,但让我们在这里坚持使用6面]具有'kinder-gentler'圆角边缘,没有尖角。
似乎btMultiSphereShape对我来说是完美的 - 我是一个没有从低级原语构建任何复杂形状的知识的人,我是一个希望使用已经内置的东西的人Bullet引擎的碰撞智能,而不是试图设计任何新的异国行为的人。
根据前言,我非常感谢一个简洁的例子:
一个。如何将参数传递给btMultiSphhereShape构造函数; 湾如何配置需要传递给btDefaultMaotionState的转换;和 C。如何设置localInertia。
我知道这是一个通用的库,其中的类几乎可以支持任何内容,但是对于初学者来说,请不要讨论精心设计的工具包的那些非常好的属性,最重要的是什么对我有帮助[我相信很多其他用户]将是一个明确的例子,将这些关键属性提供给这些细节的必要类和方法:
一个。一个尺寸相同的六面模具,让每边约2厘米的圆形立方体; 湾让'拐角'的半径为0.1厘米。
现在,还有一个请求。为了观察模具的行为,从一个简单的“下降”开始,仅考虑重力引起的力,请建议一个变换,这将导致与通常的“地板”示例碰撞产生某种有趣的翻滚结果;换句话说,它应该在圆角上撞击地板。
答案 0 :(得分:1)
我在iOS设备上使用Bullet Physics来制作骰子游戏。为了获得更逼真的骰子,我创建了一个“RoundedCube”对象,它只是一个带有斜边的立方体。这是我写的用于创建verticies的Objective-c代码
//
// 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
如果你有iOS设备,你可以在我的免费应用Amazing Dice HD on iTunes
中看到一个示例。答案 1 :(得分: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