Minor constraint refactoring, to allow SPU-side processing for PLAYSTATION 3 (added non-virtual methods)

Also comment-out some code for __SPU__ to reduce code size
Added btContactConstraint (only used on PS3 SPU right now, better to use btPersistentManifold directly for contact constraints)
Improved readblend utility library (see also usage in http://gamekit.googlecode.com with Irrlicht)

Fix for btConvexConvexAlgorithm, potential division by zero
Thanks linzner http://code.google.com/p/bullet/issues/detail?id=260
This commit is contained in:
erwin.coumans 2009-08-05 22:14:46 +00:00
parent b16f251530
commit 3e2529fcb5
21 changed files with 2980 additions and 2587 deletions

View File

@ -10,13 +10,18 @@
#ifndef _ABS_FILE_H
#define _ABS_FILE_H
typedef unsigned char uint8_t;
typedef unsigned long int uint64_t;
typedef unsigned int uint32_t;
typedef int int32_t;
#ifdef WIN32
typedef unsigned char uint8_t;
typedef unsigned long int uint64_t;
typedef unsigned int uint32_t;
typedef int int32_t;
typedef unsigned short uint16_t;
typedef short int16_t;
#else
#include <stdint.h>
#endif
/*
PLEASE NOTE: This license applies to abs-file.h ONLY; The version of
@ -194,6 +199,8 @@ static int MY_PUTS(const char *s, MY_FILETYPE *const fp) {
#else /* !USE_PHYSFS */
//#define USE_POSIX_FILES 1
#ifdef USE_POSIX_FILES
#define MY_FILETYPE FILE
#define MY_READ(p,s,n,fp) fread(p,s,n,fp)
#define MY_WRITE(p,s,n,fp) fwrite(p,s,n,fp)
@ -221,6 +228,33 @@ static long MY_FILELENGTH(FILE *fp) {
fseek(fp, currentpos, SEEK_SET); /* restore previous cursor position */
return newpos;
}
#else
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MY_FILETYPE char
long MY_FILELENGTH(FILE *fp);
MY_FILETYPE* MY_OPEN_FOR_READ(const char *const filename);
int MY_GETC(MY_FILETYPE *const fp);
void MY_SEEK(MY_FILETYPE* fp,int pos);
#define MY_REWIND(fp) MY_SEEK(fp,0)
int MY_READ(unsigned char* dest,int size,int num,MY_FILETYPE* fp);
void MY_CLOSE(MY_FILETYPE* fp);
int MY_TELL(MY_FILETYPE* fp);
int MY_ATEOF(MY_FILETYPE* fp);
#ifdef __cplusplus
}
#endif
#endif //USE_POSIX_FILES
#endif /* USE_PHYSFS */
#endif /* _ABS_FILE_H */

View File

@ -0,0 +1,87 @@
#ifndef BLEND_TYPE_H
#define BLEND_TYPE_H
#include "abs-file.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _BlendField BlendField;
struct _BlendField {
char* field_bytes;
int field_bytes_count;
/* the offset into field_bytes at which each field of a
structure begins. this is so we can keep the data aligned
correctly for various architectures. a non-structure type
is equivalent to a structure with a single field.
*/
int* field_offsets;
int field_offsets_count;
};
struct _BlendBlock {
char tag[5];
uint32_t blender_pointer;
/*void* fixed_pointer;*/
int type_index;
/* a block is simply an array of its type as defined by type_index.
array_entries is an array of pointers to each entry in the block's
array.
*/
BlendField *array_entries;
int array_entries_count;
void* customData; /* for Link blocks, with custom data such as .jpg pictures etc */
int customDataSize;
};
typedef struct _BlendBlock BlendBlock;
/* the types extracted from the Blender file */
typedef struct _BlendType BlendType;
struct _BlendType {
char* name;
int size;
int is_struct;
/* if is_struct... this defines the types of each of the structure fields */
int fieldtypes_count;
int* fieldtypes; /* type indices */
int fieldnames_count;
int* fieldnames; /* name indices */
};
/* the opaque BlendFile structure */
typedef struct _BlendFile{
BlendType* types;
int types_count;
char* *names;
int names_count;
int* strc_indices;
int strc_indices_count;
BlendBlock *blocks;
int blocks_count;
int name_undef; /* index of the name we add specially for top blocks */
} BlendFile;
#ifdef __cplusplus
}
#endif
#endif //BLEND_TYPE_H

File diff suppressed because it is too large Load Diff

View File

@ -38,11 +38,11 @@
/* TODO: Doxygen me. */
/* don't worry yourself about this. */
#ifndef BlendFile
#define BlendFile void
#endif
#include "blendtype.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -101,6 +101,7 @@ typedef struct {
long entry_index; long field_index;
} BlendObject;
/* The callback type for passing to blend_foreach_block() (the callback
should return zero if it doesn't want to see any more blocks.) */
#define BLENDBLOCKCALLBACK_RETURN int
@ -312,20 +313,41 @@ typedef struct {
bDeformWeight* deform_weights;
int deform_weights_count;
} bVert;
#define BVERT_HAS_CNORMAL(BV) ((BV)->cnormal[0] != 0.0f || \
(BV)->cnormal[1] != 0.0f || \
(BV)->cnormal[2] != 0.0f)
#define BFACE_FLAG_SMOOTH 0x01
typedef struct _bImage {
void* m_packedImagePtr;
int m_sizePackedImage;
char m_imagePathName [128];
int m_ok;
int m_xrep;
int m_yrep;
} bImage;
typedef struct {
int v[4];
float rgba[4][4]; /* vertex colours */
float rgba2[4][4]; /* texture face colours (errrr...?) */
float uv[4][2];
BlendBlockPointer image_id;
bImage* m_image;
int mat;
unsigned char flags;
int m_flag;
int m_mode;
BlendBlockPointer image_id;
} bFace;
#define BFACE_HAS_TEXTURE(BF) ((BF)->image_id != NULL)
#define BFACE_IS_QUAD(BF) ((BF)->v[3] != 0)
#define BFACE_IS_TRI(BF) ((BF)->v[2] != 0 && (BF)->v[3] == 0)
@ -389,7 +411,7 @@ typedef struct {
typedef float bMatrix[4][4];
typedef struct {
typedef struct _bMesh{
bVert *vert;
int vert_count;
bFace *face;
@ -400,14 +422,17 @@ typedef struct {
typedef enum {
BOBJ_TYPE_UNKNOWN,
BOBJ_TYPE_NULL, /* indicates object has no data associated with it! */
BOBJ_TYPE_MESH
BOBJ_TYPE_MESH,
BOBJ_TYPE_INVALID_MESH,
BOBJ_TYPE_CAMERA,
BOBJ_TYPE_LAMP
} bObjType;
typedef enum {
BAQ_INCLUDE_CHILDREN = 0x0001
} bAcquireFlags;
typedef struct {
typedef struct _bObj{
bObjType type;
char *name;
@ -417,11 +442,15 @@ typedef struct {
float rotphr[3]; /* pitch/head/roll rotation component of transform (use for normals) */
float location[3]; /* location component of transform */
unsigned char transflags; /* NOT DECODED YET, RAW BYTE */
float mass;//used for rigid body dynamics
int gameflag; //used to detect object type (static, ghost, dynamic, rigid body, soft body)
int boundtype; //used to detect collision shape type
union {
void *dummy;
bMesh *mesh;
} data;
} bObj;
@ -456,4 +485,8 @@ void blend_free_texlayer(bTexLayer *tl);
void blend_acquire_texlayer_from_obj(BlendFile *bf, BlendObject *tlobj,
bTexLayer *tl);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -4,107 +4,170 @@
#include "abs-file.h"
#include "readblend.h"
#include "blendtype.h"
#define MAX_MESHES 10
bMesh gMeshes[MAX_MESHES];
int gNumMesh = 0;
#define MAX_OBJECTS 10
bObj gObjects[MAX_OBJECTS];
int gNumObjects = 0;
void crawl(BlendFile* blend_file,
BlendObject obj)
BlendObject obj)
{
BlendObject data_obj;
BlendObject data_obj;
BlendObject data_obj2;
BlendBlock* tmpBlock=0;
if (blend_object_structure_getfield(blend_file, &data_obj, obj, "totvert")) {
if (blend_object_type(blend_file, data_obj) == BLEND_OBJ_LONG32) {
long data1 = 123456;
if (blend_object_getdata(blend_file, &data1, data_obj)) {
fprintf(stderr, "TOTVERT=(%ld) ", data1);
} else {
fprintf(stderr, "FETCH ERROR\n");
}
}
}
{
const char* type_name = blend_file->types[obj.type].name;
if (strcmp(type_name,"Object")==0)
{
if (gNumObjects<MAX_OBJECTS)
{
blend_acquire_obj_from_obj(blend_file,&obj,&gObjects[gNumObjects],0);
gNumObjects++;
}
}
if (blend_object_structure_getfield(blend_file, &data_obj, obj, "co")) {
if (blend_object_type(blend_file, data_obj) == BLEND_OBJ_FLOAT) {
float data1 = 123456.7;
float data2 = 123456.8;
float data3 = 123456.9;
if (blend_object_array_getdata(blend_file, &data1, data_obj, 0,0) &&
blend_object_array_getdata(blend_file, &data2, data_obj, 0,1) &&
blend_object_array_getdata(blend_file, &data3, data_obj, 0,2)) {
fprintf(stderr, "CO=(%f,%f,%f) ", data1, data2, data3);
} else {
fprintf(stderr, "FETCH ERROR\n");
}
}
}
if (strcmp(type_name,"Mesh")==0)
{
printf("object type_name = %s\n",type_name);
if (gNumMesh<MAX_MESHES)
{
blend_acquire_mesh_from_obj(blend_file, &obj, &gMeshes[gNumMesh]);
gNumMesh++;
}
}
}
///todo: compress those 4 lines into a one-liner, using a C++ wrapper
if (blend_object_structure_getfield(blend_file, &data_obj, obj, "curscene")) {
if (blend_object_type(blend_file, data_obj) == BLEND_OBJ_POINTER) {
if (blend_object_getdata(blend_file, &tmpBlock, data_obj)) {
BlendObject blscene= blend_block_get_object(blend_file,tmpBlock,0);
if (blend_object_structure_getfield(blend_file, &data_obj,blscene , "id"))
{
if (blend_object_type(blend_file, data_obj) == BLEND_OBJ_STRUCT)
{
if (blend_object_structure_getfield(blend_file, &data_obj2,data_obj , "name"))
{
char dest[19];
int max_chars=20;
if (blend_object_getstring(blend_file, data_obj2,
dest, max_chars))
{
printf("dest=%s\n",dest);
}
}
}
}
if (blend_object_structure_getfield(blend_file, &data_obj,blscene , "world")) {
if (blend_object_type(blend_file, data_obj) == BLEND_OBJ_POINTER) {
if (blend_object_getdata(blend_file, &tmpBlock, data_obj)) {
BlendObject blworld= blend_block_get_object(blend_file,tmpBlock,0);
if (blend_object_structure_getfield(blend_file, &data_obj, blworld, "gravity"))
{
printf("Scene with world and gravity\n");
if (blend_object_type(blend_file, data_obj) == BLEND_OBJ_FLOAT) {
float data1 = 123456.7;
if (blend_object_getdata(blend_file, &data1, data_obj))
fprintf(stderr, "gravity=(%f) ", data1);
} else {
fprintf(stderr, "FETCH ERROR\n");
}
}
}
}
}
}
}
}
}
static BLENDBLOCKCALLBACK_RETURN
blockiter(BLENDBLOCKCALLBACK_ARGS) {
int i;
int entry_count = blend_block_get_entry_count(blend_file, block);
int i;
int entry_count = blend_block_get_entry_count(blend_file, block);
#if 0
const char* tagname = blend_block_get_tagname(blend_file, block);
const char* typename = blend_block_get_typename(blend_file, block);
fprintf(stderr, "block: tag=%s type=%s entries=%d ",
tagname, typename, entry_count);
const char* tagname = blend_block_get_tagname(blend_file, block);
const char* typename = blend_block_get_typename(blend_file, block);
fprintf(stderr, "block: tag=%s type=%s entries=%d ",
tagname, typename, entry_count);
#endif
for (i=0; i<entry_count; ++i) {
BlendObject obj = blend_block_get_object(blend_file, block, i);
crawl(blend_file, obj);
}
//fprintf(stderr, "\n");
return 1;
for (i=0; i<entry_count; ++i) {
BlendObject obj = blend_block_get_object(blend_file, block, i);
crawl(blend_file, obj);
}
//fprintf(stderr, "\n");
return 1;
}
int
main(int argc, char *argv[])
{
MY_FILETYPE *file;
BlendFile *bf;
int rtn = 0;
MY_FILETYPE *file;
BlendFile *bf;
int rtn = 0;
if (argc <= 1) {
fprintf(stderr, "specify filename on command line.\n");
return -1;
}
if (argc <= 1) {
fprintf(stderr, "specify filename on command line.\n");
return -1;
}
file = MY_OPEN_FOR_READ(argv[1]);
file = MY_OPEN_FOR_READ(argv[1]);
if (!file) {
fprintf(stderr, "couldn't open file. :(\n");
return -1;
}
if (!file) {
fprintf(stderr, "couldn't open file. :(\n");
return -1;
}
bf = blend_read(file);
bf = blend_read(file);
if (!bf) {
fprintf(stderr, "couldn't read blender file. :(\n");
rtn = -1;
goto closeit;
}
if (!bf) {
fprintf(stderr, "couldn't read blender file. :(\n");
rtn = -1;
goto closeit;
}
blend_dump_typedefs(bf);
blend_dump_typedefs(bf);
blend_dump_blocks(bf);
// blend_dump_blocks(bf);
fflush(stdout);
fflush(stdout);
blend_foreach_block(bf, blockiter, NULL);
blend_foreach_block(bf, blockiter, NULL);
{
BlendObject obj;
char want_name[] = "IMmetalrock.jpg";
if (blend_object_get_by_IDname(bf,&obj, want_name)) {
fprintf(stderr, "got %s.\n", want_name);
}
}
{
BlendObject obj;
char want_name[] = "IMmetalrock.jpg";
if (blend_object_get_by_IDname(bf,&obj, want_name)) {
fprintf(stderr, "got %s.\n", want_name);
}
}
blend_free(bf);
blend_free(bf);
closeit:
MY_CLOSE(file);
return rtn;
closeit:
MY_CLOSE(file);
return rtn;
}

View File

@ -207,12 +207,24 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
input.m_transformB = body1->getWorldTransform();
gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
btScalar sepDist = gjkPairDetector.getCachedSeparatingDistance()+dispatchInfo.m_convexConservativeDistanceThreshold;
//now perturbe directions to get multiple contact points
btVector3 v0,v1;
btVector3 sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized();
btPlaneSpace1(sepNormalWorldSpace,v0,v1);
btVector3 sepNormalWorldSpace;
btScalar sepDist = 0.f;
#ifdef USE_SEPDISTANCE_UTIL2
if (dispatchInfo.m_useConvexConservativeDistanceUtil)
{
sepDist = gjkPairDetector.getCachedSeparatingDistance()+dispatchInfo.m_convexConservativeDistanceThreshold;
if (sepDist>SIMD_EPSILON)
{
//now perturbe directions to get multiple contact points
sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized();
btPlaneSpace1(sepNormalWorldSpace,v0,v1);
}
}
#endif //USE_SEPDISTANCE_UTIL2
//now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
//perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points
@ -280,7 +292,7 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
#ifdef USE_SEPDISTANCE_UTIL2
if (dispatchInfo.m_useConvexConservativeDistanceUtil)
if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist>SIMD_EPSILON))
{
m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(),sepDist,body0->getWorldTransform(),body1->getWorldTransform());
}

View File

@ -29,6 +29,12 @@ Written by: Marcus Hennix
#define CONETWIST_DEF_FIX_THRESH btScalar(.05f)
SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis, const btMatrix3x3& invInertiaWorld)
{
btVector3 vec = axis * invInertiaWorld;
return axis.dot(vec);
}
btConeTwistConstraint::btConeTwistConstraint()
:btTypedConstraint(CONETWIST_CONSTRAINT_TYPE),
@ -70,8 +76,6 @@ void btConeTwistConstraint::init()
}
void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info)
{
if (m_useSolveConstraintObsolete)
@ -83,7 +87,7 @@ void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info)
{
info->m_numConstraintRows = 3;
info->nub = 3;
calcAngleInfo2();
calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld());
if(m_solveSwingLimit)
{
info->m_numConstraintRows++;
@ -101,22 +105,31 @@ void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info)
}
}
}
void btConeTwistConstraint::getInfo1NonVirtual (btConstraintInfo1* info)
{
//always reserve 6 rows: object transform is not available on SPU
info->m_numConstraintRows = 6;
info->nub = 0;
}
void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info)
{
getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld());
}
void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB)
{
calcAngleInfo2(transA,transB,invInertiaWorldA,invInertiaWorldB);
btAssert(!m_useSolveConstraintObsolete);
//retrieve matrices
btTransform body0_trans;
body0_trans = m_rbA.getCenterOfMassTransform();
btTransform body1_trans;
body1_trans = m_rbB.getCenterOfMassTransform();
// set jacobian
info->m_J1linearAxis[0] = 1;
info->m_J1linearAxis[info->rowskip+1] = 1;
info->m_J1linearAxis[2*info->rowskip+2] = 1;
btVector3 a1 = body0_trans.getBasis() * m_rbAFrame.getOrigin();
btVector3 a1 = transA.getBasis() * m_rbAFrame.getOrigin();
{
btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip);
@ -124,7 +137,7 @@ void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info)
btVector3 a1neg = -a1;
a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
}
btVector3 a2 = body1_trans.getBasis() * m_rbBFrame.getOrigin();
btVector3 a2 = transB.getBasis() * m_rbBFrame.getOrigin();
{
btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip);
@ -136,7 +149,7 @@ void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info)
int j;
for (j=0; j<3; j++)
{
info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]);
info->m_constraintError[j*info->rowskip] = k * (a2[j] + transB.getOrigin()[j] - a1[j] - transA.getOrigin()[j]);
info->m_lowerLimit[j*info->rowskip] = -SIMD_INFINITY;
info->m_upperLimit[j*info->rowskip] = SIMD_INFINITY;
}
@ -275,7 +288,7 @@ void btConeTwistConstraint::buildJacobian()
}
}
calcAngleInfo2();
calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld());
}
}
@ -593,7 +606,7 @@ static btVector3 vTwist(1,0,0); // twist axis in constraint's space
void btConeTwistConstraint::calcAngleInfo2()
void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB)
{
m_swingCorrection = btScalar(0.);
m_twistLimitSign = btScalar(0.);
@ -606,8 +619,8 @@ void btConeTwistConstraint::calcAngleInfo2()
// TODO : split rotation to pure swing and pure twist
// compute desired transforms in world
btTransform trPose(m_qTarget);
btTransform trA = getRigidBodyA().getCenterOfMassTransform() * m_rbAFrame;
btTransform trB = getRigidBodyB().getCenterOfMassTransform() * m_rbBFrame;
btTransform trA = transA * m_rbAFrame;
btTransform trB = transB * m_rbBFrame;
btTransform trDeltaAB = trB * trPose * trA.inverse();
btQuaternion qDeltaAB = trDeltaAB.getRotation();
btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z());
@ -624,8 +637,8 @@ void btConeTwistConstraint::calcAngleInfo2()
{
// compute rotation of A wrt B (in constraint space)
btQuaternion qA = getRigidBodyA().getCenterOfMassTransform().getRotation() * m_rbAFrame.getRotation();
btQuaternion qB = getRigidBodyB().getCenterOfMassTransform().getRotation() * m_rbBFrame.getRotation();
btQuaternion qA = transA.getRotation() * m_rbAFrame.getRotation();
btQuaternion qB = transB.getRotation() * m_rbBFrame.getRotation();
btQuaternion qAB = qB.inverse() * qA;
// split rotation into cone and twist
// (all this is done from B's perspective. Maybe I should be averaging axes...)
@ -673,10 +686,10 @@ void btConeTwistConstraint::calcAngleInfo2()
// you haven't set any limits;
// or you're trying to set at least one of the swing limits too small. (if so, do you really want a conetwist constraint?)
// anyway, we have either hinge or fixed joint
btVector3 ivA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(0);
btVector3 jvA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1);
btVector3 kvA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
btVector3 ivB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(0);
btVector3 ivA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
btVector3 jvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
btVector3 kvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(2);
btVector3 ivB = transB.getBasis() * m_rbBFrame.getBasis().getColumn(0);
btVector3 target;
btScalar x = ivB.dot(ivA);
btScalar y = ivB.dot(jvA);

View File

@ -110,9 +110,12 @@ public:
virtual void buildJacobian();
virtual void getInfo1 (btConstraintInfo1* info);
void getInfo1NonVirtual(btConstraintInfo1* info);
virtual void getInfo2 (btConstraintInfo2* info);
void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB);
virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep);
@ -198,7 +201,7 @@ public:
}
void calcAngleInfo();
void calcAngleInfo2();
void calcAngleInfo2(const btTransform& transA, const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB);
inline btScalar getSwingSpan1()
{

View File

@ -14,6 +14,59 @@ subject to the following restrictions:
*/
#include "btContactConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btVector3.h"
#include "btJacobianEntry.h"
#include "btContactSolverInfo.h"
#include "LinearMath/btMinMax.h"
#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
btContactConstraint::btContactConstraint()
:btTypedConstraint(CONTACT_CONSTRAINT_TYPE)
{
}
btContactConstraint::btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB)
:btTypedConstraint(CONTACT_CONSTRAINT_TYPE,rbA,rbB),
m_contactManifold(*contactManifold)
{
}
btContactConstraint::~btContactConstraint()
{
}
void btContactConstraint::setContactManifold(btPersistentManifold* contactManifold)
{
m_contactManifold = *contactManifold;
}
void btContactConstraint::getInfo1 (btConstraintInfo1* info)
{
}
void btContactConstraint::getInfo2 (btConstraintInfo2* info)
{
}
void btContactConstraint::buildJacobian()
{
}
void btContactConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep)
{
}
#include "btContactConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btVector3.h"
@ -85,345 +138,4 @@ void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1,
//response between two dynamic objects with friction
btScalar resolveSingleCollision(
btRigidBody& body1,
btRigidBody& body2,
btManifoldPoint& contactPoint,
const btContactSolverInfo& solverInfo)
{
const btVector3& pos1_ = contactPoint.getPositionWorldOnA();
const btVector3& pos2_ = contactPoint.getPositionWorldOnB();
const btVector3& normal = contactPoint.m_normalWorldOnB;
//constant over all iterations
btVector3 rel_pos1 = pos1_ - body1.getCenterOfMassPosition();
btVector3 rel_pos2 = pos2_ - body2.getCenterOfMassPosition();
btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
btVector3 vel = vel1 - vel2;
btScalar rel_vel;
rel_vel = normal.dot(vel);
btScalar Kfps = btScalar(1.) / solverInfo.m_timeStep ;
// btScalar damping = solverInfo.m_damping ;
btScalar Kerp = solverInfo.m_erp;
btScalar Kcor = Kerp *Kfps;
btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData;
btAssert(cpd);
btScalar distance = cpd->m_penetration;
btScalar positionalError = Kcor *-distance;
btScalar velocityError = cpd->m_restitution - rel_vel;// * damping;
btScalar penetrationImpulse = positionalError * cpd->m_jacDiagABInv;
btScalar velocityImpulse = velocityError * cpd->m_jacDiagABInv;
btScalar normalImpulse = penetrationImpulse+velocityImpulse;
// See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse
btScalar oldNormalImpulse = cpd->m_appliedImpulse;
btScalar sum = oldNormalImpulse + normalImpulse;
cpd->m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum;
normalImpulse = cpd->m_appliedImpulse - oldNormalImpulse;
#ifdef USE_INTERNAL_APPLY_IMPULSE
if (body1.getInvMass())
{
body1.internalApplyImpulse(contactPoint.m_normalWorldOnB*body1.getInvMass(),cpd->m_angularComponentA,normalImpulse);
}
if (body2.getInvMass())
{
body2.internalApplyImpulse(contactPoint.m_normalWorldOnB*body2.getInvMass(),cpd->m_angularComponentB,-normalImpulse);
}
#else //USE_INTERNAL_APPLY_IMPULSE
body1.applyImpulse(normal*(normalImpulse), rel_pos1);
body2.applyImpulse(-normal*(normalImpulse), rel_pos2);
#endif //USE_INTERNAL_APPLY_IMPULSE
return normalImpulse;
}
btScalar resolveSingleFriction(
btRigidBody& body1,
btRigidBody& body2,
btManifoldPoint& contactPoint,
const btContactSolverInfo& solverInfo)
{
(void)solverInfo;
const btVector3& pos1 = contactPoint.getPositionWorldOnA();
const btVector3& pos2 = contactPoint.getPositionWorldOnB();
btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition();
btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition();
btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData;
btAssert(cpd);
btScalar combinedFriction = cpd->m_friction;
btScalar limit = cpd->m_appliedImpulse * combinedFriction;
if (cpd->m_appliedImpulse>btScalar(0.))
//friction
{
//apply friction in the 2 tangential directions
// 1st tangent
btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
btVector3 vel = vel1 - vel2;
btScalar j1,j2;
{
btScalar vrel = cpd->m_frictionWorldTangential0.dot(vel);
// calculate j that moves us to zero relative velocity
j1 = -vrel * cpd->m_jacDiagABInvTangent0;
btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse0;
cpd->m_accumulatedTangentImpulse0 = oldTangentImpulse + j1;
btSetMin(cpd->m_accumulatedTangentImpulse0, limit);
btSetMax(cpd->m_accumulatedTangentImpulse0, -limit);
j1 = cpd->m_accumulatedTangentImpulse0 - oldTangentImpulse;
}
{
// 2nd tangent
btScalar vrel = cpd->m_frictionWorldTangential1.dot(vel);
// calculate j that moves us to zero relative velocity
j2 = -vrel * cpd->m_jacDiagABInvTangent1;
btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse1;
cpd->m_accumulatedTangentImpulse1 = oldTangentImpulse + j2;
btSetMin(cpd->m_accumulatedTangentImpulse1, limit);
btSetMax(cpd->m_accumulatedTangentImpulse1, -limit);
j2 = cpd->m_accumulatedTangentImpulse1 - oldTangentImpulse;
}
#ifdef USE_INTERNAL_APPLY_IMPULSE
if (body1.getInvMass())
{
body1.internalApplyImpulse(cpd->m_frictionWorldTangential0*body1.getInvMass(),cpd->m_frictionAngularComponent0A,j1);
body1.internalApplyImpulse(cpd->m_frictionWorldTangential1*body1.getInvMass(),cpd->m_frictionAngularComponent1A,j2);
}
if (body2.getInvMass())
{
body2.internalApplyImpulse(cpd->m_frictionWorldTangential0*body2.getInvMass(),cpd->m_frictionAngularComponent0B,-j1);
body2.internalApplyImpulse(cpd->m_frictionWorldTangential1*body2.getInvMass(),cpd->m_frictionAngularComponent1B,-j2);
}
#else //USE_INTERNAL_APPLY_IMPULSE
body1.applyImpulse((j1 * cpd->m_frictionWorldTangential0)+(j2 * cpd->m_frictionWorldTangential1), rel_pos1);
body2.applyImpulse((j1 * -cpd->m_frictionWorldTangential0)+(j2 * -cpd->m_frictionWorldTangential1), rel_pos2);
#endif //USE_INTERNAL_APPLY_IMPULSE
}
return cpd->m_appliedImpulse;
}
btScalar resolveSingleFrictionOriginal(
btRigidBody& body1,
btRigidBody& body2,
btManifoldPoint& contactPoint,
const btContactSolverInfo& solverInfo);
btScalar resolveSingleFrictionOriginal(
btRigidBody& body1,
btRigidBody& body2,
btManifoldPoint& contactPoint,
const btContactSolverInfo& solverInfo)
{
(void)solverInfo;
const btVector3& pos1 = contactPoint.getPositionWorldOnA();
const btVector3& pos2 = contactPoint.getPositionWorldOnB();
btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition();
btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition();
btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData;
btAssert(cpd);
btScalar combinedFriction = cpd->m_friction;
btScalar limit = cpd->m_appliedImpulse * combinedFriction;
//if (contactPoint.m_appliedImpulse>btScalar(0.))
//friction
{
//apply friction in the 2 tangential directions
{
// 1st tangent
btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
btVector3 vel = vel1 - vel2;
btScalar vrel = cpd->m_frictionWorldTangential0.dot(vel);
// calculate j that moves us to zero relative velocity
btScalar j = -vrel * cpd->m_jacDiagABInvTangent0;
btScalar total = cpd->m_accumulatedTangentImpulse0 + j;
btSetMin(total, limit);
btSetMax(total, -limit);
j = total - cpd->m_accumulatedTangentImpulse0;
cpd->m_accumulatedTangentImpulse0 = total;
body1.applyImpulse(j * cpd->m_frictionWorldTangential0, rel_pos1);
body2.applyImpulse(j * -cpd->m_frictionWorldTangential0, rel_pos2);
}
{
// 2nd tangent
btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
btVector3 vel = vel1 - vel2;
btScalar vrel = cpd->m_frictionWorldTangential1.dot(vel);
// calculate j that moves us to zero relative velocity
btScalar j = -vrel * cpd->m_jacDiagABInvTangent1;
btScalar total = cpd->m_accumulatedTangentImpulse1 + j;
btSetMin(total, limit);
btSetMax(total, -limit);
j = total - cpd->m_accumulatedTangentImpulse1;
cpd->m_accumulatedTangentImpulse1 = total;
body1.applyImpulse(j * cpd->m_frictionWorldTangential1, rel_pos1);
body2.applyImpulse(j * -cpd->m_frictionWorldTangential1, rel_pos2);
}
}
return cpd->m_appliedImpulse;
}
//velocity + friction
//response between two dynamic objects with friction
btScalar resolveSingleCollisionCombined(
btRigidBody& body1,
btRigidBody& body2,
btManifoldPoint& contactPoint,
const btContactSolverInfo& solverInfo)
{
const btVector3& pos1 = contactPoint.getPositionWorldOnA();
const btVector3& pos2 = contactPoint.getPositionWorldOnB();
const btVector3& normal = contactPoint.m_normalWorldOnB;
btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition();
btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition();
btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
btVector3 vel = vel1 - vel2;
btScalar rel_vel;
rel_vel = normal.dot(vel);
btScalar Kfps = btScalar(1.) / solverInfo.m_timeStep ;
//btScalar damping = solverInfo.m_damping ;
btScalar Kerp = solverInfo.m_erp;
btScalar Kcor = Kerp *Kfps;
btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData;
btAssert(cpd);
btScalar distance = cpd->m_penetration;
btScalar positionalError = Kcor *-distance;
btScalar velocityError = cpd->m_restitution - rel_vel;// * damping;
btScalar penetrationImpulse = positionalError * cpd->m_jacDiagABInv;
btScalar velocityImpulse = velocityError * cpd->m_jacDiagABInv;
btScalar normalImpulse = penetrationImpulse+velocityImpulse;
// See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse
btScalar oldNormalImpulse = cpd->m_appliedImpulse;
btScalar sum = oldNormalImpulse + normalImpulse;
cpd->m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum;
normalImpulse = cpd->m_appliedImpulse - oldNormalImpulse;
#ifdef USE_INTERNAL_APPLY_IMPULSE
if (body1.getInvMass())
{
body1.internalApplyImpulse(contactPoint.m_normalWorldOnB*body1.getInvMass(),cpd->m_angularComponentA,normalImpulse);
}
if (body2.getInvMass())
{
body2.internalApplyImpulse(contactPoint.m_normalWorldOnB*body2.getInvMass(),cpd->m_angularComponentB,-normalImpulse);
}
#else //USE_INTERNAL_APPLY_IMPULSE
body1.applyImpulse(normal*(normalImpulse), rel_pos1);
body2.applyImpulse(-normal*(normalImpulse), rel_pos2);
#endif //USE_INTERNAL_APPLY_IMPULSE
{
//friction
btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
btVector3 vel = vel1 - vel2;
rel_vel = normal.dot(vel);
btVector3 lat_vel = vel - normal * rel_vel;
btScalar lat_rel_vel = lat_vel.length();
btScalar combinedFriction = cpd->m_friction;
if (cpd->m_appliedImpulse > 0)
if (lat_rel_vel > SIMD_EPSILON)
{
lat_vel /= lat_rel_vel;
btVector3 temp1 = body1.getInvInertiaTensorWorld() * rel_pos1.cross(lat_vel);
btVector3 temp2 = body2.getInvInertiaTensorWorld() * rel_pos2.cross(lat_vel);
btScalar friction_impulse = lat_rel_vel /
(body1.getInvMass() + body2.getInvMass() + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2)));
btScalar normal_impulse = cpd->m_appliedImpulse * combinedFriction;
btSetMin(friction_impulse, normal_impulse);
btSetMax(friction_impulse, -normal_impulse);
body1.applyImpulse(lat_vel * -friction_impulse, rel_pos1);
body2.applyImpulse(lat_vel * friction_impulse, rel_pos2);
}
}
return normalImpulse;
}
btScalar resolveSingleFrictionEmpty(
btRigidBody& body1,
btRigidBody& body2,
btManifoldPoint& contactPoint,
const btContactSolverInfo& solverInfo);
btScalar resolveSingleFrictionEmpty(
btRigidBody& body1,
btRigidBody& body2,
btManifoldPoint& contactPoint,
const btContactSolverInfo& solverInfo)
{
(void)contactPoint;
(void)body1;
(void)body2;
(void)solverInfo;
return btScalar(0.);
}

View File

@ -16,107 +16,56 @@ subject to the following restrictions:
#ifndef CONTACT_CONSTRAINT_H
#define CONTACT_CONSTRAINT_H
///@todo: make into a proper class working with the iterative constraint solver
class btRigidBody;
#include "LinearMath/btVector3.h"
#include "LinearMath/btScalar.h"
struct btContactSolverInfo;
class btManifoldPoint;
#include "btJacobianEntry.h"
#include "btTypedConstraint.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
enum {
DEFAULT_CONTACT_SOLVER_TYPE=0,
CONTACT_SOLVER_TYPE1,
CONTACT_SOLVER_TYPE2,
USER_CONTACT_SOLVER_TYPE1,
MAX_CONTACT_SOLVER_TYPES
};
typedef btScalar (*ContactSolverFunc)(btRigidBody& body1,
btRigidBody& body2,
class btManifoldPoint& contactPoint,
const btContactSolverInfo& info);
///stores some extra information to each contact point. It is not in the contact point, because that want to keep the collision detection independent from the constraint solver.
struct btConstraintPersistentData
///btContactConstraint can be automatically created to solve contact constraints using the unified btTypedConstraint interface
ATTRIBUTE_ALIGNED16(class) btContactConstraint : public btTypedConstraint
{
inline btConstraintPersistentData()
:m_appliedImpulse(btScalar(0.)),
m_prevAppliedImpulse(btScalar(0.)),
m_accumulatedTangentImpulse0(btScalar(0.)),
m_accumulatedTangentImpulse1(btScalar(0.)),
m_jacDiagABInv(btScalar(0.)),
m_persistentLifeTime(0),
m_restitution(btScalar(0.)),
m_friction(btScalar(0.)),
m_penetration(btScalar(0.)),
m_contactSolverFunc(0),
m_frictionSolverFunc(0)
protected:
btPersistentManifold m_contactManifold;
public:
btContactConstraint();
btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB);
void setContactManifold(btPersistentManifold* contactManifold);
btPersistentManifold* getContactManifold()
{
return &m_contactManifold;
}
/// total applied impulse during most recent frame
btScalar m_appliedImpulse;
btScalar m_prevAppliedImpulse;
btScalar m_accumulatedTangentImpulse0;
btScalar m_accumulatedTangentImpulse1;
btScalar m_jacDiagABInv;
btScalar m_jacDiagABInvTangent0;
btScalar m_jacDiagABInvTangent1;
int m_persistentLifeTime;
btScalar m_restitution;
btScalar m_friction;
btScalar m_penetration;
btVector3 m_frictionWorldTangential0;
btVector3 m_frictionWorldTangential1;
btVector3 m_frictionAngularComponent0A;
btVector3 m_frictionAngularComponent0B;
btVector3 m_frictionAngularComponent1A;
btVector3 m_frictionAngularComponent1B;
const btPersistentManifold* getContactManifold() const
{
return &m_contactManifold;
}
//some data doesn't need to be persistent over frames: todo: clean/reuse this
btVector3 m_angularComponentA;
btVector3 m_angularComponentB;
ContactSolverFunc m_contactSolverFunc;
ContactSolverFunc m_frictionSolverFunc;
virtual ~btContactConstraint();
virtual void getInfo1 (btConstraintInfo1* info);
virtual void getInfo2 (btConstraintInfo2* info);
///obsolete methods
virtual void buildJacobian();
///obsolete methods
virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep);
};
///bilateral constraint between two dynamic objects
///positive distance = separation, negative distance = penetration
///resolveSingleBilateral is an obsolete methods used for vehicle friction between two dynamic objects
void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1,
btRigidBody& body2, const btVector3& pos2,
btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep);
///contact constraint resolution:
///calculate and apply impulse to satisfy non-penetration and non-negative relative velocity constraint
///positive distance = separation, negative distance = penetration
btScalar resolveSingleCollision(
btRigidBody& body1,
btRigidBody& body2,
btManifoldPoint& contactPoint,
const btContactSolverInfo& info);
btScalar resolveSingleFriction(
btRigidBody& body1,
btRigidBody& body2,
btManifoldPoint& contactPoint,
const btContactSolverInfo& solverInfo
);
btScalar resolveSingleCollisionCombined(
btRigidBody& body1,
btRigidBody& body2,
btManifoldPoint& contactPoint,
const btContactSolverInfo& solverInfo
);
#endif //CONTACT_CONSTRAINT_H

View File

@ -26,7 +26,7 @@ subject to the following restrictions:
#define HINGE_USE_OBSOLETE_SOLVER false
#ifndef __SPU__
btHingeConstraint::btHingeConstraint()
: btTypedConstraint (HINGE_CONSTRAINT_TYPE),
@ -249,7 +249,7 @@ void btHingeConstraint::buildJacobian()
m_accLimitImpulse = btScalar(0.);
// test angular limit
testLimit();
testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
//Compute K = J*W*J' for hinge axis
btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
@ -259,6 +259,166 @@ void btHingeConstraint::buildJacobian()
}
}
void btHingeConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep)
{
///for backwards compatibility during the transition to 'getInfo/getInfo2'
if (m_useSolveConstraintObsolete)
{
btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
btScalar tau = btScalar(0.3);
//linear part
if (!m_angularOnly)
{
btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
btVector3 vel1,vel2;
bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1);
bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2);
btVector3 vel = vel1 - vel2;
for (int i=0;i<3;i++)
{
const btVector3& normal = m_jac[i].m_linearJointAxis;
btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal();
btScalar rel_vel;
rel_vel = normal.dot(vel);
//positional error (zeroth order error)
btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal
btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv;
m_appliedImpulse += impulse;
btVector3 impulse_vector = normal * impulse;
btVector3 ftorqueAxis1 = rel_pos1.cross(normal);
btVector3 ftorqueAxis2 = rel_pos2.cross(normal);
bodyA.applyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse);
bodyB.applyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse);
}
}
{
///solve angular part
// get axes in world space
btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(2);
btVector3 angVelA;
bodyA.getAngularVelocity(angVelA);
btVector3 angVelB;
bodyB.getAngularVelocity(angVelB);
btVector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA);
btVector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB);
btVector3 angAorthog = angVelA - angVelAroundHingeAxisA;
btVector3 angBorthog = angVelB - angVelAroundHingeAxisB;
btVector3 velrelOrthog = angAorthog-angBorthog;
{
//solve orthogonal angular velocity correction
//btScalar relaxation = btScalar(1.);
btScalar len = velrelOrthog.length();
if (len > btScalar(0.00001))
{
btVector3 normal = velrelOrthog.normalized();
btScalar denom = getRigidBodyA().computeAngularImpulseDenominator(normal) +
getRigidBodyB().computeAngularImpulseDenominator(normal);
// scale for mass and relaxation
//velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor;
bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*velrelOrthog,-(btScalar(1.)/denom));
bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*velrelOrthog,(btScalar(1.)/denom));
}
//solve angular positional correction
btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/timeStep);
btScalar len2 = angularError.length();
if (len2>btScalar(0.00001))
{
btVector3 normal2 = angularError.normalized();
btScalar denom2 = getRigidBodyA().computeAngularImpulseDenominator(normal2) +
getRigidBodyB().computeAngularImpulseDenominator(normal2);
//angularError *= (btScalar(1.)/denom2) * relaxation;
bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*angularError,(btScalar(1.)/denom2));
bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*angularError,-(btScalar(1.)/denom2));
}
// solve limit
if (m_solveLimit)
{
btScalar amplitude = ( (angVelB - angVelA).dot( axisA )*m_relaxationFactor + m_correction* (btScalar(1.)/timeStep)*m_biasFactor ) * m_limitSign;
btScalar impulseMag = amplitude * m_kHinge;
// Clamp the accumulated impulse
btScalar temp = m_accLimitImpulse;
m_accLimitImpulse = btMax(m_accLimitImpulse + impulseMag, btScalar(0) );
impulseMag = m_accLimitImpulse - temp;
bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,impulseMag * m_limitSign);
bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-(impulseMag * m_limitSign));
}
}
//apply motor
if (m_enableAngularMotor)
{
//todo: add limits too
btVector3 angularLimit(0,0,0);
btVector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB;
btScalar projRelVel = velrel.dot(axisA);
btScalar desiredMotorVel = m_motorTargetVelocity;
btScalar motor_relvel = desiredMotorVel - projRelVel;
btScalar unclippedMotorImpulse = m_kHinge * motor_relvel;;
// accumulated impulse clipping:
btScalar fMaxImpulse = m_maxMotorImpulse;
btScalar newAccImpulse = m_accMotorImpulse + unclippedMotorImpulse;
btScalar clippedMotorImpulse = unclippedMotorImpulse;
if (newAccImpulse > fMaxImpulse)
{
newAccImpulse = fMaxImpulse;
clippedMotorImpulse = newAccImpulse - m_accMotorImpulse;
}
else if (newAccImpulse < -fMaxImpulse)
{
newAccImpulse = -fMaxImpulse;
clippedMotorImpulse = newAccImpulse - m_accMotorImpulse;
}
m_accMotorImpulse += clippedMotorImpulse;
bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,clippedMotorImpulse);
bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-clippedMotorImpulse);
}
}
}
}
#endif //__SPU__
void btHingeConstraint::getInfo1(btConstraintInfo1* info)
@ -272,52 +432,77 @@ void btHingeConstraint::getInfo1(btConstraintInfo1* info)
{
info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular
info->nub = 1;
//always add the row, to avoid computation (data is not available yet)
//prepare constraint
testLimit();
testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
if(getSolveLimit() || getEnableAngularMotor())
{
info->m_numConstraintRows++; // limit 3rd anguar as well
info->nub--;
}
}
}
void btHingeConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
{
if (m_useSolveConstraintObsolete)
{
info->m_numConstraintRows = 0;
info->nub = 0;
}
else
{
//always add the 'limit' row, to avoid computation (data is not available yet)
info->m_numConstraintRows = 6; // Fixed 3 linear + 2 angular
info->nub = 0;
}
}
void btHingeConstraint::getInfo2 (btConstraintInfo2* info)
{
getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity());
}
void btHingeConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB)
{
btAssert(!m_useSolveConstraintObsolete);
int i, s = info->rowskip;
int i, skip = info->rowskip;
// transforms in world space
btTransform trA = m_rbA.getCenterOfMassTransform()*m_rbAFrame;
btTransform trB = m_rbB.getCenterOfMassTransform()*m_rbBFrame;
btTransform trA = transA*m_rbAFrame;
btTransform trB = transB*m_rbBFrame;
// pivot point
btVector3 pivotAInW = trA.getOrigin();
btVector3 pivotBInW = trB.getOrigin();
// linear (all fixed)
info->m_J1linearAxis[0] = 1;
info->m_J1linearAxis[s + 1] = 1;
info->m_J1linearAxis[2 * s + 2] = 1;
btVector3 a1 = pivotAInW - m_rbA.getCenterOfMassTransform().getOrigin();
info->m_J1linearAxis[skip + 1] = 1;
info->m_J1linearAxis[2 * skip + 2] = 1;
btVector3 a1 = pivotAInW - transA.getOrigin();
{
btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + s);
btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * s);
btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + skip);
btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * skip);
btVector3 a1neg = -a1;
a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
}
btVector3 a2 = pivotBInW - m_rbB.getCenterOfMassTransform().getOrigin();
btVector3 a2 = pivotBInW - transB.getOrigin();
{
btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + s);
btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * s);
btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + skip);
btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * skip);
a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
}
// linear RHS
btScalar k = info->fps * info->erp;
for(i = 0; i < 3; i++)
{
info->m_constraintError[i * s] = k * (pivotBInW[i] - pivotAInW[i]);
info->m_constraintError[i * skip] = k * (pivotBInW[i] - pivotAInW[i]);
}
// make rotations around X and Y equal
// the hinge axis should be the only unconstrained
@ -436,8 +621,8 @@ void btHingeConstraint::getInfo2 (btConstraintInfo2* info)
btScalar bounce = m_relaxationFactor;
if(bounce > btScalar(0.0))
{
btScalar vel = m_rbA.getAngularVelocity().dot(ax1);
vel -= m_rbB.getAngularVelocity().dot(ax1);
btScalar vel = angVelA.dot(ax1);
vel -= angVelB.dot(ax1);
// only apply bounce if the velocity is incoming, and if the
// resulting c[] exceeds what we already have.
if(limit == 1)
@ -470,163 +655,6 @@ void btHingeConstraint::getInfo2 (btConstraintInfo2* info)
void btHingeConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep)
{
///for backwards compatibility during the transition to 'getInfo/getInfo2'
if (m_useSolveConstraintObsolete)
{
btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
btScalar tau = btScalar(0.3);
//linear part
if (!m_angularOnly)
{
btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
btVector3 vel1,vel2;
bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1);
bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2);
btVector3 vel = vel1 - vel2;
for (int i=0;i<3;i++)
{
const btVector3& normal = m_jac[i].m_linearJointAxis;
btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal();
btScalar rel_vel;
rel_vel = normal.dot(vel);
//positional error (zeroth order error)
btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal
btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv;
m_appliedImpulse += impulse;
btVector3 impulse_vector = normal * impulse;
btVector3 ftorqueAxis1 = rel_pos1.cross(normal);
btVector3 ftorqueAxis2 = rel_pos2.cross(normal);
bodyA.applyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse);
bodyB.applyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse);
}
}
{
///solve angular part
// get axes in world space
btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(2);
btVector3 angVelA;
bodyA.getAngularVelocity(angVelA);
btVector3 angVelB;
bodyB.getAngularVelocity(angVelB);
btVector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA);
btVector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB);
btVector3 angAorthog = angVelA - angVelAroundHingeAxisA;
btVector3 angBorthog = angVelB - angVelAroundHingeAxisB;
btVector3 velrelOrthog = angAorthog-angBorthog;
{
//solve orthogonal angular velocity correction
btScalar relaxation = btScalar(1.);
btScalar len = velrelOrthog.length();
if (len > btScalar(0.00001))
{
btVector3 normal = velrelOrthog.normalized();
btScalar denom = getRigidBodyA().computeAngularImpulseDenominator(normal) +
getRigidBodyB().computeAngularImpulseDenominator(normal);
// scale for mass and relaxation
//velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor;
bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*velrelOrthog,-(btScalar(1.)/denom));
bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*velrelOrthog,(btScalar(1.)/denom));
}
//solve angular positional correction
btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/timeStep);
btScalar len2 = angularError.length();
if (len2>btScalar(0.00001))
{
btVector3 normal2 = angularError.normalized();
btScalar denom2 = getRigidBodyA().computeAngularImpulseDenominator(normal2) +
getRigidBodyB().computeAngularImpulseDenominator(normal2);
//angularError *= (btScalar(1.)/denom2) * relaxation;
bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*angularError,(btScalar(1.)/denom2));
bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*angularError,-(btScalar(1.)/denom2));
}
// solve limit
if (m_solveLimit)
{
btScalar amplitude = ( (angVelB - angVelA).dot( axisA )*m_relaxationFactor + m_correction* (btScalar(1.)/timeStep)*m_biasFactor ) * m_limitSign;
btScalar impulseMag = amplitude * m_kHinge;
// Clamp the accumulated impulse
btScalar temp = m_accLimitImpulse;
m_accLimitImpulse = btMax(m_accLimitImpulse + impulseMag, btScalar(0) );
impulseMag = m_accLimitImpulse - temp;
bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,impulseMag * m_limitSign);
bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-(impulseMag * m_limitSign));
}
}
//apply motor
if (m_enableAngularMotor)
{
//todo: add limits too
btVector3 angularLimit(0,0,0);
btVector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB;
btScalar projRelVel = velrel.dot(axisA);
btScalar desiredMotorVel = m_motorTargetVelocity;
btScalar motor_relvel = desiredMotorVel - projRelVel;
btScalar unclippedMotorImpulse = m_kHinge * motor_relvel;;
// accumulated impulse clipping:
btScalar fMaxImpulse = m_maxMotorImpulse;
btScalar newAccImpulse = m_accMotorImpulse + unclippedMotorImpulse;
btScalar clippedMotorImpulse = unclippedMotorImpulse;
if (newAccImpulse > fMaxImpulse)
{
newAccImpulse = fMaxImpulse;
clippedMotorImpulse = newAccImpulse - m_accMotorImpulse;
}
else if (newAccImpulse < -fMaxImpulse)
{
newAccImpulse = -fMaxImpulse;
clippedMotorImpulse = newAccImpulse - m_accMotorImpulse;
}
m_accMotorImpulse += clippedMotorImpulse;
bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,clippedMotorImpulse);
bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-clippedMotorImpulse);
}
}
}
}
@ -637,12 +665,16 @@ void btHingeConstraint::updateRHS(btScalar timeStep)
}
btScalar btHingeConstraint::getHingeAngle()
{
const btVector3 refAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(0);
const btVector3 refAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1);
const btVector3 swingAxis = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(1);
return getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
}
btScalar btHingeConstraint::getHingeAngle(const btTransform& transA,const btTransform& transB)
{
const btVector3 refAxis0 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
const btVector3 refAxis1 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
const btVector3 swingAxis = transB.getBasis() * m_rbBFrame.getBasis().getColumn(1);
btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
return m_referenceSign * angle;
}
@ -676,10 +708,10 @@ void btHingeConstraint::testLimit()
#else
void btHingeConstraint::testLimit()
void btHingeConstraint::testLimit(const btTransform& transA,const btTransform& transB)
{
// Compute limit information
m_hingeAngle = getHingeAngle();
m_hingeAngle = getHingeAngle(transA,transB);
m_correction = btScalar(0.);
m_limitSign = btScalar(0.);
m_solveLimit = false;
@ -741,7 +773,7 @@ void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt)
}
// compute angular velocity
btScalar curAngle = getHingeAngle();
btScalar curAngle = getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
btScalar dAngle = targetAngle - curAngle;
m_motorTargetVelocity = dAngle / dt;
}

View File

@ -26,7 +26,7 @@ class btRigidBody;
/// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
/// axis defines the orientation of the hinge axis
class btHingeConstraint : public btTypedConstraint
ATTRIBUTE_ALIGNED16(class) btHingeConstraint : public btTypedConstraint
{
#ifdef IN_PARALLELL_SOLVER
public:
@ -81,8 +81,12 @@ public:
virtual void getInfo1 (btConstraintInfo1* info);
void getInfo1NonVirtual(btConstraintInfo1* info);
virtual void getInfo2 (btConstraintInfo2* info);
void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB);
virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep);
void updateRHS(btScalar timeStep);
@ -174,7 +178,9 @@ public:
btScalar getHingeAngle();
void testLimit();
btScalar getHingeAngle(const btTransform& transA,const btTransform& transB);
void testLimit(const btTransform& transA,const btTransform& transB);
const btTransform& getAFrame() const { return m_rbAFrame; };

View File

@ -28,7 +28,7 @@ subject to the following restrictions:
/// Jacobian entry is an abstraction that allows to describe constraints
/// it can be used in combination with a constraint solver
/// Can be used to relate the effect of an impulse to the constraint error
class btJacobianEntry
ATTRIBUTE_ALIGNED16(class) btJacobianEntry
{
public:
btJacobianEntry() {};

View File

@ -43,6 +43,7 @@ m_useSolveConstraintObsolete(false)
void btPoint2PointConstraint::buildJacobian()
{
///we need it for both methods
{
m_appliedImpulse = btScalar(0.);
@ -66,10 +67,15 @@ void btPoint2PointConstraint::buildJacobian()
}
}
}
void btPoint2PointConstraint::getInfo1 (btConstraintInfo1* info)
{
getInfo1NonVirtual(info);
}
void btPoint2PointConstraint::getInfo1NonVirtual (btConstraintInfo1* info)
{
if (m_useSolveConstraintObsolete)
{
@ -82,22 +88,26 @@ void btPoint2PointConstraint::getInfo1 (btConstraintInfo1* info)
}
}
void btPoint2PointConstraint::getInfo2 (btConstraintInfo2* info)
{
getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
}
void btPoint2PointConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans)
{
btAssert(!m_useSolveConstraintObsolete);
//retrieve matrices
btTransform body0_trans;
body0_trans = m_rbA.getCenterOfMassTransform();
btTransform body1_trans;
body1_trans = m_rbB.getCenterOfMassTransform();
// anchor points in global coordinates with respect to body PORs.
// set jacobian
info->m_J1linearAxis[0] = 1;
info->m_J1linearAxis[info->rowskip+1] = 1;
info->m_J1linearAxis[2*info->rowskip+2] = 1;
info->m_J1linearAxis[info->rowskip+1] = 1;
info->m_J1linearAxis[2*info->rowskip+2] = 1;
btVector3 a1 = body0_trans.getBasis()*getPivotInA();
{
@ -150,6 +160,7 @@ void btPoint2PointConstraint::getInfo2 (btConstraintInfo2* info)
void btPoint2PointConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep)
{
if (m_useSolveConstraintObsolete)
{
btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA;
@ -220,6 +231,7 @@ void btPoint2PointConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolv
normal[i] = 0;
}
}
}
void btPoint2PointConstraint::updateRHS(btScalar timeStep)

View File

@ -36,7 +36,7 @@ struct btConstraintSetting
};
/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space
class btPoint2PointConstraint : public btTypedConstraint
ATTRIBUTE_ALIGNED16(class) btPoint2PointConstraint : public btTypedConstraint
{
#ifdef IN_PARALLELL_SOLVER
public:
@ -65,8 +65,11 @@ public:
virtual void getInfo1 (btConstraintInfo1* info);
void getInfo1NonVirtual (btConstraintInfo1* info);
virtual void getInfo2 (btConstraintInfo2* info);
void getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans);
virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep);

View File

@ -22,7 +22,7 @@ class btIDebugDraw;
#include "btSolverBody.h"
#include "btSolverConstraint.h"
#include "btTypedConstraint.h"
#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
///The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (iterative LCP) method.
class btSequentialImpulseConstraintSolver : public btConstraintSolver

View File

@ -126,6 +126,7 @@ void btSliderConstraint::buildJacobian()
void btSliderConstraint::buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB)
{
#ifndef __SPU__
//calculate transforms
m_calculatedTransformA = rbA.getCenterOfMassTransform() * frameInA;
m_calculatedTransformB = rbB.getCenterOfMassTransform() * frameInB;
@ -175,10 +176,10 @@ void btSliderConstraint::buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, co
// clear accumulator for motors
m_accumulatedLinMotorImpulse = btScalar(0.0);
m_accumulatedAngMotorImpulse = btScalar(0.0);
#endif //__SPU__
}
void btSliderConstraint::getInfo1(btConstraintInfo1* info)
{
if (m_useSolveConstraintObsolete)
@ -191,7 +192,7 @@ void btSliderConstraint::getInfo1(btConstraintInfo1* info)
info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular
info->nub = 2;
//prepare constraint
calculateTransforms();
calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
testLinLimits();
if(getSolveLinLimit() || getPoweredLinMotor())
{
@ -207,14 +208,34 @@ void btSliderConstraint::getInfo1(btConstraintInfo1* info)
}
}
void btSliderConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
{
info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used)
info->nub = 0;
}
void btSliderConstraint::getInfo2(btConstraintInfo2* info)
{
btAssert(!m_useSolveConstraintObsolete);
int i, s = info->rowskip;
const btTransform& trA = getCalculatedTransformA();
const btTransform& trB = getCalculatedTransformB();
getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(),m_rbB.getLinearVelocity(), m_rbA.getInvMass(),m_rbB.getInvMass());
}
void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB, const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass )
{
//prepare constraint
calculateTransforms(transA,transB);
testLinLimits();
testAngLimits();
const btTransform& trA = getCalculatedTransformA();
const btTransform& trB = getCalculatedTransformB();
btAssert(!m_useSolveConstraintObsolete);
int i, s = info->rowskip;
btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f);
// make rotations around Y and Z equal
// the slider axis should be the only unconstrained
@ -269,12 +290,12 @@ void btSliderConstraint::getInfo2(btConstraintInfo2* info)
// result in three equations, so we project along the planespace vectors
// so that sliding along the slider axis is disregarded. for symmetry we
// also consider rotation around center of mass of two bodies (factA and factB).
btTransform bodyA_trans = m_rbA.getCenterOfMassTransform();
btTransform bodyB_trans = m_rbB.getCenterOfMassTransform();
btTransform bodyA_trans = transA;
btTransform bodyB_trans = transB;
int s2 = 2 * s, s3 = 3 * s;
btVector3 c;
btScalar miA = m_rbA.getInvMass();
btScalar miB = m_rbB.getInvMass();
btScalar miA = rbAinvMass;
btScalar miB = rbBinvMass;
btScalar miS = miA + miB;
btScalar factA, factB;
if(miS > btScalar(0.f))
@ -389,8 +410,8 @@ void btSliderConstraint::getInfo2(btConstraintInfo2* info)
btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin());
if(bounce > btScalar(0.0))
{
btScalar vel = m_rbA.getLinearVelocity().dot(ax1);
vel -= m_rbB.getLinearVelocity().dot(ax1);
btScalar vel = linVelA.dot(ax1);
vel -= linVelB.dot(ax1);
vel *= signFact;
// only apply bounce if the velocity is incoming, and if the
// resulting c[] exceeds what we already have.
@ -539,6 +560,7 @@ void btSliderConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBod
void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btSolverBody& bodyA,btRigidBody& rbB, btSolverBody& bodyB)
{
#ifndef __SPU__
int i;
// linear
btVector3 velA;
@ -719,22 +741,24 @@ void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btSolverBody& body
bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*axisA,-angImpulse);
}
}
#endif //__SPU__
}
void btSliderConstraint::calculateTransforms(void){
void btSliderConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB)
{
if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete))
{
m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA;
m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB;
m_calculatedTransformA = transA * m_frameInA;
m_calculatedTransformB = transB * m_frameInB;
}
else
{
m_calculatedTransformA = m_rbB.getCenterOfMassTransform() * m_frameInB;
m_calculatedTransformB = m_rbA.getCenterOfMassTransform() * m_frameInA;
m_calculatedTransformA = transB * m_frameInB;
m_calculatedTransformB = transA * m_frameInA;
}
m_realPivotAInW = m_calculatedTransformA.getOrigin();
m_realPivotBInW = m_calculatedTransformB.getOrigin();

View File

@ -131,9 +131,13 @@ public:
// overrides
virtual void buildJacobian();
virtual void getInfo1 (btConstraintInfo1* info);
void getInfo1NonVirtual(btConstraintInfo1* info);
virtual void getInfo2 (btConstraintInfo2* info);
void getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass);
virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep);
@ -215,13 +219,13 @@ public:
void buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB);
void solveConstraintInt(btRigidBody& rbA, btSolverBody& bodyA,btRigidBody& rbB, btSolverBody& bodyB);
// shared code used by ODE solver
void calculateTransforms(void);
void testLinLimits(void);
void calculateTransforms(const btTransform& transA,const btTransform& transB);
void testLinLimits();
void testLinLimits2(btConstraintInfo2* info);
void testAngLimits(void);
void testAngLimits();
// access for PE Solver
btVector3 getAncorInA(void);
btVector3 getAncorInB(void);
btVector3 getAncorInA();
btVector3 getAncorInB();
};

View File

@ -30,7 +30,8 @@ enum btTypedConstraintType
HINGE_CONSTRAINT_TYPE,
CONETWIST_CONSTRAINT_TYPE,
D6_CONSTRAINT_TYPE,
SLIDER_CONSTRAINT_TYPE
SLIDER_CONSTRAINT_TYPE,
CONTACT_CONSTRAINT_TYPE
};
///TypedConstraint is the baseclass for Bullet constraints and vehicles

View File

@ -81,6 +81,11 @@ public:
virtual void setNumTasks(int numTasks);
virtual int getNumTasks() const
{
return 1;
}
};
#endif //SEQUENTIAL_THREAD_SUPPORT_H

View File

@ -183,6 +183,8 @@ void Win32ThreadSupport::startThreads(const Win32ThreadConstructionInfo& threadC
m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads);
m_completeHandles.resize(threadConstructionInfo.m_numThreads);
m_maxNumTasks = threadConstructionInfo.m_numThreads;
for (int i=0;i<threadConstructionInfo.m_numThreads;i++)
{
printf("starting thread %d\n",i);