1
  1. I am posting here because I have not been successful in finding a helpful answer either directly on the Bullet Physics forum or any of those associated forums which have either ported the library [JBullet, BulletCS] or incorporated it in their own product [Blender, Panda3d]. Here it seems, at least if I can ask the question properly, the odds seem best of getting a helpful reply.

  2. I want to simulate the rolling of dice. All the examples I can find seem content with using a Box shape. Mine is an interest in children's games, not Las Vegas. The defining difference, at least in my application, is that the dice [whether 6-sided, or something else, but let's just stick with 6-sided here] have 'kinder-gentler' rounded edges with no pointed corners.

  3. It seems that btMultiSphereShape would be just perfect for me -- me being someone who does not have the knowledge to construct any complex shape from lower-level primitives, me being someone who hopes to use what is already built into the collision intelligence of the Bullet engine, not someone trying to engineer any new, exotic behavior.

  4. With that preface I would really appreciate a succinct example of:

    a. how to pass the arguments to the btMultiSphhereShape constructor; b. how to configure the transform that needs to be passed to btDefaultMaotionState; and c. how to set the localInertia.

  5. I understand that this is a general-purpose library with classes that can support almost anything, but please, for a beginner, instead of discussions of those very nice attributes of a well-conceived toolkit, what would be most helpful to me [and I believe to many other users] would be a clear example of supplying those key properties to the necessary classes and methods to these specifics:

    a. a six-sided die with equal dimensions, let's make the rounded cube about 2cm per side; b. let's have the radius of the 'corners' a gentle 0.1.cm.

  6. Now, one more request, please. In order to observe the behavior of the die beginning with a simple 'drop', taking into account only forces due to gravity, please suggest a transform that will result in some kind of interesting tumbling result from a collision against the usual 'floor' example; in other words, it should impact the floor on a rounded corner.

4

2 回答 2

1

我在 iOS 设备上使用 Bullet Physics 创建了一个骰子游戏。为了获得更逼真的骰子,我创建了一个“RoundedCube”对象,它只是一个带有斜边的立方体。这是我为创建顶点而编写的 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;
    }

@结尾

如果您有 iOS 设备,您可以在 iTunes 上的免费应用程序 Amazing Dice HD 中看到它的外观示例

于 2012-01-25T19:43:43.690 回答
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
于 2012-01-28T05:31:59.770 回答