btCriticalSection* Win32ThreadSupport::createCriticalSection()
{
	unsigned char* mem = (unsigned char*) btAlignedAlloc(sizeof(btWin32CriticalSection),16);
	btWin32CriticalSection* cs = new(mem) btWin32CriticalSection();
	return cs;
}
btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc*	stackAlloc,btPoolAllocator*	persistentManifoldPool,btPoolAllocator*	collisionAlgorithmPool)
{

    void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16);
    m_simplexSolver = new (mem)btVoronoiSimplexSolver();

#define USE_EPA 1
#ifdef USE_EPA
    mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16);
    m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver;
#else
    mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16);
    m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver;
#endif//USE_EPA	


    //default CreationFunctions, filling the m_doubleDispatch table
    mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16);
    m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver);
    mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
    m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc;
    mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
    m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
    mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16);
    m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc;
    mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16);
    m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc;
    mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16);
    m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc;

    mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16);
    m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc;
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
    mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
    m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc;
    mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
    m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc;
    m_boxSphereCF->m_swapped = true;
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM

    mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
    m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
    mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
    m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
    m_triangleSphereCF->m_swapped = true;

    mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16);
    m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc;

    //convex versus plane
    mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
    m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
    mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
    m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
    m_planeConvexCF->m_swapped = true;

    ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
    int maxSize = sizeof(btConvexConvexAlgorithm);
    int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
    int maxSize3 = sizeof(btCompoundCollisionAlgorithm);
    int sl = sizeof(btConvexSeparatingDistanceUtil);
    sl = sizeof(btGjkPairDetector);
    int	collisionAlgorithmMaxElementSize = btMax(maxSize,maxSize2);
    collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3);

    if (constructionInfo.m_stackAlloc)
    {
        m_ownsStackAllocator = false;
        this->m_stackAlloc = constructionInfo.m_stackAlloc;
    } else
    {
        m_ownsStackAllocator = true;
        void* mem = btAlignedAlloc(sizeof(btStackAlloc),16);
        m_stackAlloc = new(mem)btStackAlloc(constructionInfo.m_defaultStackAllocatorSize);
    }

    if (constructionInfo.m_persistentManifoldPool)
    {
        m_ownsPersistentManifoldPool = false;
        m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool;
    } else
    {
        m_ownsPersistentManifoldPool = true;
        void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
        m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
    }

    if (constructionInfo.m_collisionAlgorithmPool)
    {
        m_ownsCollisionAlgorithmPool = false;
        m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool;
    } else
    {
        m_ownsCollisionAlgorithmPool = true;
        void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
        m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
    }


}
Пример #3
0
void	ParticlesDemo::initPhysics()
{
	
	setTexturing(false);
	setShadows(false);

//	setCameraDistance(80.f);
	setCameraDistance(3.0f);
//	m_cameraTargetPosition.setValue(50, 10, 0);
	m_cameraTargetPosition.setValue(0, 0, 0);
//	m_azi = btScalar(0.f);
//	m_ele = btScalar(0.f);
	m_azi = btScalar(45.f);
	m_ele = btScalar(30.f);
	setFrustumZPlanes(0.1f, 10.f);

	///collision configuration contains default setup for memory, collision setup

	btDefaultCollisionConstructionInfo dci;
	dci.m_defaultMaxPersistentManifoldPoolSize=50000;
	dci.m_defaultMaxCollisionAlgorithmPoolSize=50000;

	m_collisionConfiguration = new btDefaultCollisionConfiguration(dci);

	///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
	m_dispatcher = new	btCollisionDispatcher(m_collisionConfiguration);

	m_pairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16))btHashedOverlappingPairCache(); 


//	m_broadphase = new btDbvtBroadphase(m_pairCache);
	m_broadphase = new btNullBroadphase();

	///the default constraint solver
	m_solver = new btSequentialImpulseConstraintSolver();

	m_pWorld = new btParticlesDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, 65536);

	m_dialogDynamicsWorld = new GL_DialogDynamicsWorld();
	GL_DialogWindow* settings = m_dialogDynamicsWorld->createDialog(50,0,280,280,"CPU fallback");
	
	m_pWorld->m_useCpuControls[0] = 0;
	GL_ToggleControl* ctrl = 0;
	m_pWorld->m_useCpuControls[SIMSTAGE_INTEGRATE_MOTION] = m_dialogDynamicsWorld->createToggle(settings,"Integrate Motion");
	m_pWorld->m_useCpuControls[SIMSTAGE_COMPUTE_CELL_ID] = m_dialogDynamicsWorld->createToggle(settings,"Compute Cell ID");
	m_pWorld->m_useCpuControls[SIMSTAGE_SORT_CELL_ID] = m_dialogDynamicsWorld->createToggle(settings,"Sort Cell ID");
	m_pWorld->m_useCpuControls[SIMSTAGE_FIND_CELL_START] = m_dialogDynamicsWorld->createToggle(settings,"Find Cell Start");
	m_pWorld->m_useCpuControls[SIMSTAGE_COLLIDE_PARTICLES] = m_dialogDynamicsWorld->createToggle(settings,"Collide Particles");
	

	for(int i = 1; i < SIMSTAGE_TOTAL; i++)
	{
		m_pWorld->m_useCpuControls[i]->m_active = false;
	}
#if defined(CL_PLATFORM_MINI_CL)
	// these kernels use barrier()
	m_pWorld->m_useCpuControls[SIMSTAGE_SORT_CELL_ID]->m_active = true; 
	m_pWorld->m_useCpuControls[SIMSTAGE_FIND_CELL_START]->m_active = true; 
#endif

	// out of date
//	m_pWorld->m_useCpuControls[SIMSTAGE_SORT_CELL_ID]->m_active = true; 
//m_pWorld->m_useCpuControls[SIMSTAGE_FIND_CELL_START]->m_active = true; 


	m_dynamicsWorld = m_pWorld;

	m_pWorld->getSimulationIslandManager()->setSplitIslands(true);
	m_pWorld->setGravity(btVector3(0,-10.,0));
	m_pWorld->getSolverInfo().m_numIterations = 4;

	{
//		btCollisionShape* colShape = new btSphereShape(btScalar(1.0f));
/*	
		btCollisionShape* colShape = new btSphereShape(DEF_PARTICLE_RADIUS);
		m_collisionShapes.push_back(colShape);
		btTransform startTransform;
		startTransform.setIdentity();
		btScalar	mass(1.f);
		btVector3 localInertia(0,0,0);
		colShape->calculateLocalInertia(mass,localInertia);
		float start_x = START_POS_X - ARRAY_SIZE_X * DIST * btScalar(0.5f);
		float start_y = START_POS_Y - ARRAY_SIZE_Y * DIST * btScalar(0.5f);
		float start_z = START_POS_Z - ARRAY_SIZE_Z * DIST * btScalar(0.5f);
		startTransform.setOrigin(btVector3(start_x, start_y, start_z));
		btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia);
		rbInfo.m_startWorldTransform = startTransform;
		btRigidBody* body = new btRigidBody(rbInfo);
		m_pWorld->addRigidBody(body);
		*/

		init_scene_directly();
	}
	clientResetScene();
	m_pWorld->initDeviceData();
}
Пример #4
0
plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height)
{
	void* mem = btAlignedAlloc(sizeof(btCylinderShape),16);
	return (plCollisionShapeHandle) new (mem)btCylinderShape(btVector3(radius,height,radius));
}
Пример #5
0
plPhysicsSdkHandle	plNewBulletSdk()
{
	void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16);
	return (plPhysicsSdkHandle)new (mem)btPhysicsSdk;
}
Пример #6
0
btPairCachingGhostObject::btPairCachingGhostObject()
{
	m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
}
Пример #7
0
plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z)
{
	void* mem = btAlignedAlloc(sizeof(btBoxShape),16);
	return (plCollisionShapeHandle) new (mem)btBoxShape(btVector3(x,y,z));
}
Пример #8
0
PlCylinderShape* pl_cylindershape_new(PlReal radius, PlReal height)
{
	void* mem = btAlignedAlloc(sizeof(btCylinderShape),16);
	return (PlCylinderShape*) new (mem)btCylinderShape(btVector3(radius,height,radius));
}
Пример #9
0
/* Convex Meshes */
PlConvexHullShape* pl_convexhullshape_new()
{
	void* mem = btAlignedAlloc(sizeof(btConvexHullShape),16);
	return (PlConvexHullShape*) new (mem)btConvexHullShape();
}
Пример #10
0
PlBoxShape* pl_boxshape_new(PlReal x, PlReal y, PlReal z)
{
	void* mem = btAlignedAlloc(sizeof(btBoxShape),16);
	return (PlBoxShape*) new (mem)btBoxShape(btVector3(x,y,z));
}
Пример #11
0
PlConeShape* pl_coneshape_new(PlReal radius, PlReal height)
{
	void* mem = btAlignedAlloc(sizeof(btConeShape),16);
	return (PlConeShape*) new (mem)btConeShape(radius,height);
}
Пример #12
0
PlSphereShape* pl_sphereshape_new(PlReal radius)
{
	void* mem = btAlignedAlloc(sizeof(btSphereShape),16);
	return (PlSphereShape*) new (mem)btSphereShape(radius);
	
}
Пример #13
0
PlPhysicsSdk*	pl_physicssdk_new()
{
	void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16);
	return (PlPhysicsSdk*)new (mem)btPhysicsSdk;
}
Пример #14
0
PlQuaternion* pl_quaternion_new()
{
	PlQuaternion* mem = (PlQuaternion*)(btAlignedAlloc(4 * sizeof(PlReal),16));
	return (PlQuaternion*)mem;
}
Пример #15
0
void	InternalEdgeDemo::initPhysics()
{
	
	setTexturing(true);
	setShadows(false);//true);

	#define TRISIZE 10.f

     gContactAddedCallback = CustomMaterialCombinerCallback;

#define USE_TRIMESH_SHAPE 1
#ifdef USE_TRIMESH_SHAPE

	int vertStride = sizeof(btVector3);
	int indexStride = 3*sizeof(int);

	
	const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1);

	gVertices = new btVector3[totalVerts];
	gIndices = new int[totalTriangles*3];

	int i;


	setVertexPositions(waveheight,0.f);
	
	
	//gVertices[1].setY(21.1);
	//gVertices[1].setY(121.1);
	gVertices[1].setY(.1f);

#ifdef ROTATE_GROUND
	//gVertices[1].setY(-1.1);
#else
	//gVertices[1].setY(0.1);
	//gVertices[1].setY(-0.1);
	//gVertices[1].setY(-20.1);
	//gVertices[1].setY(-20);
#endif
	
	int index=0;
	for ( i=0;i<NUM_VERTS_X-1;i++)
	{
		for (int j=0;j<NUM_VERTS_Y-1;j++)
		{

#ifdef SWAP_WINDING
#ifdef SHIFT_INDICES
			gIndices[index++] = j*NUM_VERTS_X+i;
			gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
			gIndices[index++] = j*NUM_VERTS_X+i+1;
			
			gIndices[index++] = j*NUM_VERTS_X+i;
			gIndices[index++] = (j+1)*NUM_VERTS_X+i;
			gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
			
#else
			gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
			gIndices[index++] = j*NUM_VERTS_X+i+1;
			gIndices[index++] = j*NUM_VERTS_X+i;

			gIndices[index++] = (j+1)*NUM_VERTS_X+i;
			gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
			gIndices[index++] = j*NUM_VERTS_X+i;
#endif //SHIFT_INDICES
#else //SWAP_WINDING

#ifdef SHIFT_INDICES
			gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
			gIndices[index++] = j*NUM_VERTS_X+i;
			gIndices[index++] = j*NUM_VERTS_X+i+1;

#ifdef TEST_INCONSISTENT_WINDING
			gIndices[index++] = j*NUM_VERTS_X+i;
			gIndices[index++] = (j+1)*NUM_VERTS_X+i;
			gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;

#else //TEST_INCONSISTENT_WINDING
			gIndices[index++] = (j+1)*NUM_VERTS_X+i;
			gIndices[index++] = j*NUM_VERTS_X+i;
			gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
#endif //TEST_INCONSISTENT_WINDING
			
			
			
#else //SHIFT_INDICES
			gIndices[index++] = j*NUM_VERTS_X+i;
			gIndices[index++] = j*NUM_VERTS_X+i+1;
			gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;

			gIndices[index++] = j*NUM_VERTS_X+i;
			gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
			gIndices[index++] = (j+1)*NUM_VERTS_X+i;
#endif //SHIFT_INDICES

#endif //SWAP_WINDING

			
		}
	}

	m_indexVertexArrays = new btTriangleIndexVertexArray(totalTriangles,
		gIndices,
		indexStride,
		totalVerts,(btScalar*) &gVertices[0].x(),vertStride);

	
	bool useQuantizedAabbCompression = true;

//comment out the next line to read the BVH from disk (first run the demo once to create the BVH)
#define SERIALIZE_TO_DISK 1
#ifdef SERIALIZE_TO_DISK
	btVector3 aabbMin(-1000,-1000,-1000),aabbMax(1000,1000,1000);
	
	trimeshShape  = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression,aabbMin,aabbMax);
	m_collisionShapes.push_back(trimeshShape);
	
	
	///we can serialize the BVH data 
	void* buffer = 0;
	int numBytes = trimeshShape->getOptimizedBvh()->calculateSerializeBufferSize();
	buffer = btAlignedAlloc(numBytes,16);
	bool swapEndian = false;
	trimeshShape->getOptimizedBvh()->serialize(buffer,numBytes,swapEndian);
#ifdef __QNX__
	FILE* file = fopen("app/native/bvh.bin","wb");
#else
	FILE* file = fopen("bvh.bin","wb");
#endif
	fwrite(buffer,1,numBytes,file);
	fclose(file);
	btAlignedFree(buffer);
	


#else

	trimeshShape  = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression,false);

	char* fileName = "bvh.bin";

#ifdef __QNX__
	char* fileName = "app/native/bvh.bin";
#else
	char* fileName = "bvh.bin";
#endif
	int size=0;
	btOptimizedBvh* bvh = 0;

	if (fseek(file, 0, SEEK_END) || (size = ftell(file)) == EOF || fseek(file, 0, SEEK_SET)) {        /* File operations denied? ok, just close and return failure */
		printf("Error: cannot get filesize from %s\n", fileName);
		exit(0);
	} else
	{

		fseek(file, 0, SEEK_SET);

		int buffersize = size+btOptimizedBvh::getAlignmentSerializationPadding();

		void* buffer = btAlignedAlloc(buffersize,16);
		int read = fread(buffer,1,size,file);
		fclose(file);
		bool swapEndian = false;
		bvh = btOptimizedBvh::deSerializeInPlace(buffer,buffersize,swapEndian);
	}

	trimeshShape->setOptimizedBvh(bvh);

#endif

	btCollisionShape* groundShape = trimeshShape;

	btTriangleInfoMap* triangleInfoMap = new btTriangleInfoMap();
	

	btGenerateInternalEdgeInfo(trimeshShape,triangleInfoMap);
	


#else
	btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50));

	m_collisionShapes.push_back(groundShape);

#endif //USE_TRIMESH_SHAPE

	m_collisionConfiguration = new btDefaultCollisionConfiguration();
	

	m_dispatcher = new	btCollisionDispatcher(m_collisionConfiguration);


	
	m_broadphase = new btDbvtBroadphase();
	m_solver = new btSequentialImpulseConstraintSolver();
	m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
/*
m_dynamicsWorld->getSolverInfo().m_splitImpulse = true;
	m_dynamicsWorld->getSolverInfo().m_splitImpulsePenetrationThreshold = 1e30f;
	m_dynamicsWorld->getSolverInfo().m_maxErrorReduction = 1e30f;
	m_dynamicsWorld->getSolverInfo().m_erp  =1.f;
	m_dynamicsWorld->getSolverInfo().m_erp2 = 1.f;
*/

	m_dynamicsWorld->setGravity(btVector3(0,-10,0));

	
	float mass = 0.f;
	btTransform	startTransform;
	startTransform.setIdentity();
	startTransform.setOrigin(btVector3(0,-2,0));


	btConvexHullShape* colShape = new btConvexHullShape();
	for (int i=0;i<TaruVtxCount;i++)
	{
		btVector3 vtx(TaruVtx[i*3],TaruVtx[i*3+1],TaruVtx[i*3+2]);
		colShape->addPoint(vtx);
	}
	//this will enable polyhedral contact clipping, better quality, slightly slower
	colShape->initializePolyhedralFeatures();

	//the polyhedral contact clipping can use either GJK or SAT test to find the separating axis
	m_dynamicsWorld->getDispatchInfo().m_enableSatConvex=false;

	m_collisionShapes.push_back(colShape);

	{
		for (int i=0;i<1;i++)
		{
			startTransform.setOrigin(btVector3(-10.f+i*3.f,2.2f+btScalar(i)*0.1f,-1.3f));
			btRigidBody* body = localCreateRigidBody(10, startTransform,colShape);
			body->setActivationState(DISABLE_DEACTIVATION);
			body->setLinearVelocity(btVector3(0,0,-1));
			//body->setContactProcessingThreshold(0.f);
		}
	}
	{
		btBoxShape* colShape = new btBoxShape(btVector3(1,1,1));
		colShape->initializePolyhedralFeatures();
		m_collisionShapes.push_back(colShape);
		startTransform.setOrigin(btVector3(-16.f+i*3.f,1.f+btScalar(i)*0.1f,-1.3f));
		btRigidBody* body = localCreateRigidBody(10, startTransform,colShape);
		body->setActivationState(DISABLE_DEACTIVATION);
		body->setLinearVelocity(btVector3(0,0,-1));
	}

	startTransform.setIdentity();
#ifdef ROTATE_GROUND
	btQuaternion orn(btVector3(0,0,1),SIMD_PI);
	startTransform.setOrigin(btVector3(-20,0,0));
	startTransform.setRotation(orn);
#endif //ROTATE_GROUND

	staticBody = localCreateRigidBody(mass, startTransform,groundShape);
	//staticBody->setContactProcessingThreshold(-0.031f);
	staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);//STATIC_OBJECT);

	//enable custom material callback
	staticBody->setCollisionFlags(staticBody->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);

	getDynamicsWorld()->setDebugDrawer(&gDebugDrawer);
	setDebugMode(btIDebugDraw::DBG_DrawText|btIDebugDraw::DBG_NoHelpText+btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints);


#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
	btSetDebugDrawer(&gDebugDrawer);
#endif //BT_INTERNAL_EDGE_DEBUG_DRAW

	
}
Пример #16
0
PlCompoundShape* pl_compoundshape_new()
{
	void* mem = btAlignedAlloc(sizeof(btCompoundShape),16);
	return (PlCompoundShape*) new (mem)btCompoundShape();
}
btTriangleIndexVertexArray* btCollisionWorldImporter::createMeshInterface(btStridingMeshInterfaceData&  meshData)
{
	btTriangleIndexVertexArray* meshInterface = createTriangleMeshContainer();

	for (int i=0;i<meshData.m_numMeshParts;i++)
	{
		btIndexedMesh meshPart;
		meshPart.m_numTriangles = meshData.m_meshPartsPtr[i].m_numTriangles;
		meshPart.m_numVertices = meshData.m_meshPartsPtr[i].m_numVertices;


		if (meshData.m_meshPartsPtr[i].m_indices32)
		{
			meshPart.m_indexType = PHY_INTEGER;
			meshPart.m_triangleIndexStride = 3*sizeof(int);
			int* indexArray = (int*)btAlignedAlloc(sizeof(int)*3*meshPart.m_numTriangles,16);
			m_indexArrays.push_back(indexArray);
			for (int j=0;j<3*meshPart.m_numTriangles;j++)
			{
				indexArray[j] = meshData.m_meshPartsPtr[i].m_indices32[j].m_value;
			}
			meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
		} else
		{
			if (meshData.m_meshPartsPtr[i].m_3indices16)
			{
				meshPart.m_indexType = PHY_SHORT;
				meshPart.m_triangleIndexStride = sizeof(short int)*3;//sizeof(btShortIntIndexTripletData);

				short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int)*3*meshPart.m_numTriangles,16);
				m_shortIndexArrays.push_back(indexArray);

				for (int j=0;j<meshPart.m_numTriangles;j++)
				{
					indexArray[3*j] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[0];
					indexArray[3*j+1] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[1];
					indexArray[3*j+2] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[2];
				}

				meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
			}
			if (meshData.m_meshPartsPtr[i].m_indices16)
			{
				meshPart.m_indexType = PHY_SHORT;
				meshPart.m_triangleIndexStride = 3*sizeof(short int);
				short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int)*3*meshPart.m_numTriangles,16);
				m_shortIndexArrays.push_back(indexArray);
				for (int j=0;j<3*meshPart.m_numTriangles;j++)
				{
					indexArray[j] = meshData.m_meshPartsPtr[i].m_indices16[j].m_value;
				}

				meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
			}

			if (meshData.m_meshPartsPtr[i].m_3indices8)
			{
				meshPart.m_indexType = PHY_UCHAR;
				meshPart.m_triangleIndexStride = sizeof(unsigned char)*3;

				unsigned char* indexArray = (unsigned char*)btAlignedAlloc(sizeof(unsigned char)*3*meshPart.m_numTriangles,16);
				m_charIndexArrays.push_back(indexArray);

				for (int j=0;j<meshPart.m_numTriangles;j++)
				{
					indexArray[3*j] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[0];
					indexArray[3*j+1] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[1];
					indexArray[3*j+2] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[2];
				}

				meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
			}
		}

		if (meshData.m_meshPartsPtr[i].m_vertices3f)
		{
			meshPart.m_vertexType = PHY_FLOAT;
			meshPart.m_vertexStride = sizeof(btVector3FloatData);
			btVector3FloatData* vertices = (btVector3FloatData*) btAlignedAlloc(sizeof(btVector3FloatData)*meshPart.m_numVertices,16);
			m_floatVertexArrays.push_back(vertices);

			for (int j=0;j<meshPart.m_numVertices;j++)
			{
				vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[0];
				vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[1];
				vertices[j].m_floats[2] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[2];
				vertices[j].m_floats[3] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[3];
			}
			meshPart.m_vertexBase = (const unsigned char*)vertices;
		} else
		{
			meshPart.m_vertexType = PHY_DOUBLE;
			meshPart.m_vertexStride = sizeof(btVector3DoubleData);


			btVector3DoubleData* vertices = (btVector3DoubleData*) btAlignedAlloc(sizeof(btVector3DoubleData)*meshPart.m_numVertices,16);
			m_doubleVertexArrays.push_back(vertices);

			for (int j=0;j<meshPart.m_numVertices;j++)
			{
				vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[0];
				vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[1];
				vertices[j].m_floats[2] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[2];
				vertices[j].m_floats[3] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[3];
			}
			meshPart.m_vertexBase = (const unsigned char*)vertices;
		}

		if (meshPart.m_triangleIndexBase && meshPart.m_vertexBase)
		{
			meshInterface->addIndexedMesh(meshPart,meshPart.m_indexType);
		}
	}

	return meshInterface;
}
Пример #18
0
PlVector3* pl_vector3_new()
{

	PlVector3* mem = (PlVector3*)(btAlignedAlloc(3 * sizeof(PlReal),16));
	return mem;
}
Пример #19
0
plCollisionShapeHandle plNewSphereShape(plReal radius)
{
	void* mem = btAlignedAlloc(sizeof(btSphereShape),16);
	return (plCollisionShapeHandle) new (mem)btSphereShape(radius);
	
}
	virtual bool	processOverlap(btBroadphasePair& collisionPair)
	{


		//PPU version
		//(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo);

		//only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD
		btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE);

		//by default, Bullet will use this near callback
		{
			///userInfo is used to determine if the SPU has to handle this case or not (skip PPU tasks)
			if (!collisionPair.m_internalTmpValue)
			{
				collisionPair.m_internalTmpValue = 1;
			}
			if (!collisionPair.m_algorithm)
			{
				btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
				btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;

				btCollisionAlgorithmConstructionInfo ci;
				ci.m_dispatcher1 = m_dispatcher;
				ci.m_manifold = 0;

				if (m_dispatcher->needsCollision(colObj0,colObj1))
				{
					int	proxyType0 = colObj0->getCollisionShape()->getShapeType();
					int	proxyType1 = colObj1->getCollisionShape()->getShapeType();
					bool supportsSpuDispatch = m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1) 
						&& (colObj0->getCollisionFlags() != btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) 
						&& (colObj1->getCollisionFlags() != btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING);

					if (proxyType0 == COMPOUND_SHAPE_PROXYTYPE)
					{
						btCompoundShape* compound = (btCompoundShape*)colObj0->getCollisionShape();
						if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES)
						{
							//printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES);
							supportsSpuDispatch = false;
						}
					}

					if (proxyType1 == COMPOUND_SHAPE_PROXYTYPE)
					{
						btCompoundShape* compound = (btCompoundShape*)colObj1->getCollisionShape();
						if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES)
						{
							//printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES);
							supportsSpuDispatch = false;
						}
					}

					if (supportsSpuDispatch)
					{

						int so = sizeof(SpuContactManifoldCollisionAlgorithm);
#ifdef ALLOCATE_SEPARATELY
						void* mem = btAlignedAlloc(so,16);//m_dispatcher->allocateCollisionAlgorithm(so);
#else
						void* mem = m_dispatcher->allocateCollisionAlgorithm(so);
#endif
						collisionPair.m_algorithm = new(mem) SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1);
						collisionPair.m_internalTmpValue =  2;
					} else
					{
						collisionPair.m_algorithm = m_dispatcher->findAlgorithm(colObj0,colObj1);
						collisionPair.m_internalTmpValue = 3;
					}
				} 
			}
		}
		return false;
	}
Пример #21
0
plCollisionShapeHandle plNewConeShape(plReal radius, plReal height)
{
	void* mem = btAlignedAlloc(sizeof(btConeShape),16);
	return (plCollisionShapeHandle) new (mem)btConeShape(radius,height);
}
Пример #22
0
void	BasicDemo::initPhysics()
{
	setTexturing(false);
	setShadows(false);

#if OECAKE_LOADER
	setCameraDistance(80.);
	m_cameraTargetPosition.setValue(50, 10, 0);
#else
	#if LARGE_DEMO
		setCameraDistance(btScalar(SCALING*100.));
	#else
		setCameraDistance(btScalar(SCALING*20.));
	#endif
	m_cameraTargetPosition.setValue(START_POS_X, -START_POS_Y-20, START_POS_Z);
#endif
	m_azi = btScalar(0.f);
	m_ele = btScalar(0.f);

	///collision configuration contains default setup for memory, collision setup

	btDefaultCollisionConstructionInfo dci;
	dci.m_defaultMaxPersistentManifoldPoolSize=50000;
	dci.m_defaultMaxCollisionAlgorithmPoolSize=50000;

	m_collisionConfiguration = new btDefaultCollisionConfiguration(dci);

	///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
	m_dispatcher = new	btCollisionDispatcher(m_collisionConfiguration);
	m_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE,BOX_SHAPE_PROXYTYPE,new btEmptyAlgorithm::CreateFunc);

	m_dispatcher->setNearCallback(cudaDemoNearCallback);

	
#if USE_CUDA_DEMO_PAIR_CASHE
	gPairCache = new (btAlignedAlloc(sizeof(btGpuDemoPairCache),16)) btGpuDemoPairCache(MAX_PROXIES, 24, MAX_SMALL_PROXIES); 
#else
	gPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16))btHashedOverlappingPairCache(); 
#endif


	btVector3 numOfCells = (gWorldMax - gWorldMin) / (2. * SCALING);
	int numOfCellsX = (int)numOfCells[0];
	int numOfCellsY = (int)numOfCells[1];
	int numOfCellsZ = (int)numOfCells[2];

//	m_broadphase = new btAxisSweep3(gWorldMin, gWorldMax, MAX_PROXIES,gPairCache);
	m_broadphase = new btDbvtBroadphase(gPairCache);
//	m_broadphase = new btGpu3DGridBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,24,24);
//	m_broadphase = new btCudaBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,24,24);


	///the default constraint solver
	m_solver = new btSequentialImpulseConstraintSolver();

	btGpuDemoDynamicsWorld* pDdw = new btGpuDemoDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, MAX_PROXIES);
	m_dynamicsWorld = pDdw;
	pDdw->getSimulationIslandManager()->setSplitIslands(true);
	pDdw->setObjRad(SCALING);
	pDdw->setWorldMin(gWorldMin);
	pDdw->setWorldMax(gWorldMax);
//	gUseCPUSolver = true;
	pDdw->setUseCPUSolver(gUseCPUSolver);
	gUseBulletNarrowphase = false;
	pDdw->setUseBulletNarrowphase(gUseBulletNarrowphase);

//	m_dynamicsWorld->setGravity(btVector3(0,0,0));
	m_dynamicsWorld->setGravity(btVector3(0,-10.,0));
	m_dynamicsWorld->getSolverInfo().m_numIterations = 4;

	{
		//create a few dynamic rigidbodies
		// Re-using the same collision is better for memory usage and performance



#if 1
		#define SPRADIUS btScalar(SCALING*0.1f)
		#define SPRPOS btScalar(SCALING*0.05f)
		static btVector3 sSphPos[8];
		
		for (int k=0;k<8;k++)
		{
			sSphPos[k].setValue((k-4)*0.25*SCALING,0,0);
		}
		
		btVector3 inertiaHalfExtents(SPRADIUS,  SPRADIUS,  SPRADIUS);
		static btScalar sSphRad[8] = 
		{
//			 SPRADIUS,  SPRADIUS,  SPRADIUS, SPRADIUS,SPRADIUS,  SPRADIUS,  SPRADIUS, 0.3
			 SPRADIUS,  SPRADIUS,  SPRADIUS, SPRADIUS,SPRADIUS,  SPRADIUS,  SPRADIUS, SPRADIUS
		};
//		sSphPos[0].setX(sSphPos[0].getX()-0.15);
		#undef SPR
		btMultiSphereShape* colShape[2];
		colShape[0] = new btMultiSphereShape( sSphPos, sSphRad, 8);
		colShape[1] = new btMultiSphereShape( sSphPos, sSphRad, 2);

		//btCollisionShape* colShape = new btSphereShape(btScalar(1.));
		m_collisionShapes.push_back(colShape[0]);
		m_collisionShapes.push_back(colShape[1]);
#endif

		/// Create Dynamic Objects
		btTransform startTransform;
		startTransform.setIdentity();

		btScalar	mass(0.f);

		//rigidbody is dynamic if and only if mass is non zero, otherwise static
		bool isDynamic = (mass != 0.f);

		btVector3 localInertia(0,0,0);

#if OECAKE_LOADER
	BasicDemoOecakeLoader	loader(this);
	if (!loader.processFile("test1.oec"))
	{
		loader.processFile("../../test1.oec");
	}
#if 0 // perfomance test : work-in-progress
	{ // add more object, but share their shapes
		int numNewObjects = 500;
		mass = 1.f;
		for(int n_obj = 0; n_obj < numNewObjects; n_obj++)
		{
			btDefaultMotionState* myMotionState= 0;
			btVector3 localInertia(0,0,0);
			btTransform worldTransform;
			worldTransform.setIdentity();
			btScalar fx = fRandMinMax(-30., 30.);
			btScalar fy = fRandMinMax(5., 30.);
			worldTransform.setOrigin(btVector3(fx, fy, 0.f));
			int sz = m_collisionShapes.size();
			btMultiSphereShape* multiSphere = (btMultiSphereShape*)m_collisionShapes[1];
			myMotionState = new btDefaultMotionState(worldTransform);
			multiSphere->calculateLocalInertia(mass, localInertia);
			btRigidBody* body = new btRigidBody(mass,myMotionState,multiSphere,localInertia);	
			body->setLinearFactor(btVector3(1,1,0));
			body->setAngularFactor(btVector3(0,0,1));
			body->setWorldTransform(worldTransform);
			getDynamicsWorld()->addRigidBody(body);
		}
	}
#endif

#else
#if (!SPEC_TEST)
		float start_x = START_POS_X - ARRAY_SIZE_X * SCALING;
		float start_y = START_POS_Y - ARRAY_SIZE_Y * SCALING;
		float start_z = START_POS_Z - ARRAY_SIZE_Z * SCALING;

		int collisionShapeIndex = 0;
		for (int k=0;k<ARRAY_SIZE_Y;k++)
		{
			for (int i=0;i<ARRAY_SIZE_X;i++)
			{
				for(int j = 0;j<ARRAY_SIZE_Z;j++)
				{
					float offs = (2. * (float)rand() / (float)RAND_MAX - 1.f) * 0.05f;
					startTransform.setOrigin(SCALING*btVector3(
										2.0*SCALING*i + start_x + offs,
										2.0*SCALING*k + start_y + offs,
										2.0*SCALING*j + start_z));

					if (isDynamic)
						colShape[collisionShapeIndex]->calculateLocalInertia(mass,localInertia);


			
					//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
					//btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
					btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape[collisionShapeIndex],localInertia);
					collisionShapeIndex = 1 - collisionShapeIndex;
					rbInfo.m_startWorldTransform=startTransform;
					btRigidBody* body = new btRigidBody(rbInfo);
					m_dynamicsWorld->addRigidBody(body);
				}
			}
		}
#else//SPEC_TEST
		// narrowphase test - 2 bodies at the same position
		float start_x = START_POS_X;
//		float start_y = START_POS_Y;
		float start_y = gWorldMin[1] + SCALING * 0.7f + 5.f;
		float start_z = START_POS_Z;
		startTransform.setOrigin(SCALING*btVector3(start_x,start_y,start_z));
		btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape[0],localInertia);
		rbInfo.m_startWorldTransform=startTransform;
		btRigidBody* body = new btRigidBody(rbInfo);
		m_dynamicsWorld->addRigidBody(body);

		btPoint2PointConstraint * p2pConstr =  new btPoint2PointConstraint(*body, btVector3(1., 0., 0.));
		m_dynamicsWorld->addConstraint(p2pConstr);

		startTransform.setOrigin(SCALING*btVector3(start_x-2.f, start_y,start_z));
		rbInfo.m_startWorldTransform=startTransform;
		btRigidBody* body1 = new btRigidBody(rbInfo);
		m_dynamicsWorld->addRigidBody(body1);

		p2pConstr =  new btPoint2PointConstraint(*body, *body1, btVector3(-1., 0., 0.), btVector3(1., 0., 0.));
		m_dynamicsWorld->addConstraint(p2pConstr);


#endif//SPEC_TEST
#endif //OE_CAKE_LOADER
	}
	// now set Ids used by collision detector and constraint solver
	int numObjects = m_dynamicsWorld->getNumCollisionObjects();
	btCollisionObjectArray& collisionObjects = m_dynamicsWorld->getCollisionObjectArray();
	for(int i = 0; i < numObjects; i++)
	{
		btCollisionObject* colObj = collisionObjects[i];
		colObj->setCompanionId(i+1); // 0 reserved for the "world" object
		btCollisionShape* pShape = colObj->getCollisionShape();
		int shapeType = pShape->getShapeType();
		if(shapeType == MULTI_SPHERE_SHAPE_PROXYTYPE)
		{
			btMultiSphereShape* pMs = (btMultiSphereShape*)pShape;
			int numSpheres = pMs->getSphereCount();
			pDdw->addMultiShereObject(numSpheres, i + 1);
			for(int j = 0; j < numSpheres; j++)
			{
				btVector3 sphPos = pMs->getSpherePosition(j);
				float sphRad = pMs->getSphereRadius(j);
				pDdw->addSphere(sphPos, sphRad);
			}
		}
		else
		{
			btAssert(0);
		}
	}
#if OECAKE_LOADER
	clientResetScene();
#endif
}
Пример #23
0
plCollisionShapeHandle plNewCompoundShape()
{
	void* mem = btAlignedAlloc(sizeof(btCompoundShape),16);
	return (plCollisionShapeHandle) new (mem)btCompoundShape();
}
Пример #24
0
void	SpheresGridDemo::initPhysics()
{
	
	setTexturing(false);
	setShadows(false);

	setCameraDistance(80.);
	m_cameraTargetPosition.setValue(50, 10, 0);
	m_azi = btScalar(0.f);
	m_ele = btScalar(0.f);

	///collision configuration contains default setup for memory, collision setup

	btDefaultCollisionConstructionInfo dci;
	dci.m_defaultMaxPersistentManifoldPoolSize=50000;
	dci.m_defaultMaxCollisionAlgorithmPoolSize=50000;

	m_collisionConfiguration = new btDefaultCollisionConfiguration(dci);

	///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
	m_dispatcher = new	btCollisionDispatcher(m_collisionConfiguration);

	m_pairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16))btHashedOverlappingPairCache(); 


//	m_broadphase = new btDbvtBroadphase(m_pairCache);
	m_broadphase = new btNullBroadphase();

	///the default constraint solver
	m_solver = new btSequentialImpulseConstraintSolver();

#ifdef INTEGRATION_DEMO
	m_pWorldI = new btIntegrationDemoDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, 65536);
#endif

#ifdef SPHERES_DEMO
	m_pWorldS = new btSpheresGridDemoDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, 65536);
#endif

#ifdef SPHERES_DEMO
	m_dialogDynamicsWorld = new GL_DialogDynamicsWorld();
	GL_DialogWindow* settings = m_dialogDynamicsWorld->createDialog(50,0,280,280,"CPU fallback");
	
	m_pWorldS->m_useCpuControls[0] = 0;
	GL_ToggleControl* ctrl = 0;
	m_pWorldS->m_useCpuControls[SIMSTAGE_APPLY_GRAVITY] = m_dialogDynamicsWorld->createToggle(settings,"Apply Gravity");
	m_pWorldS->m_useCpuControls[SIMSTAGE_COMPUTE_CELL_ID] = m_dialogDynamicsWorld->createToggle(settings,"Compute Cell ID");
	m_pWorldS->m_useCpuControls[SIMSTAGE_SORT_CELL_ID] = m_dialogDynamicsWorld->createToggle(settings,"Sort Cell ID");
	m_pWorldS->m_useCpuControls[SIMSTAGE_FIND_CELL_START] = m_dialogDynamicsWorld->createToggle(settings,"Find Cell Start");
	m_pWorldS->m_useCpuControls[SIMSTAGE_FIND_PAIRS] = m_dialogDynamicsWorld->createToggle(settings,"Find Pairs");
	m_pWorldS->m_useCpuControls[SIMSTAGE_SCAN_PAIRS] = m_dialogDynamicsWorld->createToggle(settings,"Scan Pairs");
	m_pWorldS->m_useCpuControls[SIMSTAGE_COMPACT_PAIRS] = m_dialogDynamicsWorld->createToggle(settings,"Compact Pairs");
	m_pWorldS->m_useCpuControls[SIMSTAGE_COMPUTE_BATCHES] = m_dialogDynamicsWorld->createToggle(settings,"Compute Batches");
	m_pWorldS->m_useCpuControls[SIMSTAGE_COMPUTE_CONTACTS] = m_dialogDynamicsWorld->createToggle(settings,"Compute Contacts");
	m_pWorldS->m_useCpuControls[SIMSTAGE_SOLVE_CONSTRAINTS] = m_dialogDynamicsWorld->createToggle(settings,"Solve Constraints");
	m_pWorldS->m_useCpuControls[SIMSTAGE_INTEGRATE_TRANSFORMS] = m_dialogDynamicsWorld->createToggle(settings,"Integrate Transforms");
	m_pWorldS->m_useCpuControls[SIMSTAGE_KERNEL_COLLIDE_SPHERE_WALLS] = m_dialogDynamicsWorld->createToggle(settings,"Collide Sphere Walls");
	

	for(int i = 1; i < SIMSTAGE_TOTAL; i++)
	{
		m_pWorldS->m_useCpuControls[i]->m_active = false;
	}
#if defined(CL_PLATFORM_MINI_CL)
	m_pWorldS->m_useCpuControls[SIMSTAGE_SCAN_PAIRS]->m_active = true; 
	m_pWorldS->m_useCpuControls[SIMSTAGE_SORT_CELL_ID]->m_active = true; 
	m_pWorldS->m_useCpuControls[SIMSTAGE_COMPUTE_CONTACTS]->m_active = true; 
	

#endif
#if defined(CL_PLATFORM_AMD)
	m_pWorldS->m_useCpuControls[SIMSTAGE_SORT_CELL_ID]->m_active = true; // sloooow, incorrect, crashes application
	m_pWorldS->m_useCpuControls[SIMSTAGE_FIND_CELL_START]->m_active = true; // run-time error "Unimplemented"
	m_pWorldS->m_useCpuControls[SIMSTAGE_SCAN_PAIRS]->m_active = true; // works, but very slow (up to 100 times)
	m_pWorldS->m_useCpuControls[SIMSTAGE_COMPUTE_BATCHES]->m_active = true; // run-time error "Unimplemented"
#endif

#endif //#ifdef SPHERES_DEMO


	if(m_demoType == DEMO_INTEGRATION)
	{
#ifdef INTEGRATION_DEMO
		m_dynamicsWorld = m_pWorldI;
#endif
	}
	else
	{
#ifdef SPHERES_DEMO
		m_dynamicsWorld = m_pWorldS;
#endif //#ifdef SPHERES_DEMO
	}
#ifdef INTEGRATION_DEMO
	m_pWorldI->getSimulationIslandManager()->setSplitIslands(true);
	m_pWorldI->setGravity(btVector3(0,-10.,0));
	m_pWorldI->getSolverInfo().m_numIterations = 4;
#endif //INTEGRATION_DEMO

#ifdef SPHERES_DEMO
	m_pWorldS->getSimulationIslandManager()->setSplitIslands(true);
	m_pWorldS->setGravity(btVector3(0,-10.,0));
	m_pWorldS->getSolverInfo().m_numIterations = 4;
#endif //#ifdef SPHERES_DEMO

	{
		btCollisionShape* colShape = new btSphereShape(btScalar(1.0f));
		m_collisionShapes.push_back(colShape);
		btTransform startTransform;
		startTransform.setIdentity();
		btScalar	mass(1.f);
		btVector3 localInertia(0,0,0);
		colShape->calculateLocalInertia(mass,localInertia);
		float start_x = START_POS_X - ARRAY_SIZE_X * DIST * btScalar(0.5f);
		float start_y = START_POS_Y - ARRAY_SIZE_Y * DIST * btScalar(0.5f);
		float start_z = START_POS_Z - ARRAY_SIZE_Z * DIST * btScalar(0.5f);
	#if USE_BULLET_BODIES
		// may be very slow for > 10K bodies
		printf("\nGenerating bodies ...\n");
		int total = ARRAY_SIZE_X * ARRAY_SIZE_Y * ARRAY_SIZE_Z;
		int done = 0;
		for (int k=0;k<ARRAY_SIZE_Y;k++)
		{
			for (int i=0;i<ARRAY_SIZE_X;i++)
			{
				for(int j = 0;j<ARRAY_SIZE_Z;j++)
				{
					startTransform.setOrigin(btVector3(
										DIST*i + start_x,
										DIST*k + start_y,
										DIST*j + start_z));
					btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia);
					rbInfo.m_startWorldTransform = startTransform;
					btRigidBody* body = new btRigidBody(rbInfo);
					m_pWorldI->addRigidBody(body);
					done++;
				}
			}
			printf("%6d of %6d\r", done, total);
			fflush(stdout);
		}
		printf("\n... Done!\n");
	#else
		// add just one sphere
#ifdef INTEGRATION_DEMO
		startTransform.setOrigin(btVector3(start_x, start_y, start_z));
		btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia);
		rbInfo.m_startWorldTransform = startTransform;
		btRigidBody* body = new btRigidBody(rbInfo);
		m_pWorldI->addRigidBody(body);
#endif
		// now fill m_hPos and m_hLinVel directly
		init_scene_directly();
	#endif
	}
	btDynamicsWorld* tmpW = m_dynamicsWorld;
#ifdef SPHERES_DEMO
	m_dynamicsWorld = m_pWorldS;
	SpheresGridDemoOecakeLoader	loader(this);
	//loader.processFile("test1.oec");
	#if 1 /// stress test
		btCompoundShape* compound = new btCompoundShape();
		btSphereShape* sphere = new btSphereShape(1.f);
		btTransform localTrans;
		localTrans.setIdentity();
		localTrans.setOrigin(btVector3(0,0,0));
		compound->addChildShape(localTrans,sphere);
		//localTrans.setOrigin(btVector3(-1,0,0));
		//compound->addChildShape(localTrans,sphere);

		btTransform trans;
		trans.setIdentity();

		btVector3 offset(0.00001,0.00001,0.00001);
		for (int j=0;j<STRESS_X;j++)
		for (int i=0;i<STRESS_Y;i++)
		{
			trans.setOrigin(offset*i+btVector3(25+j*6,30+i*3,0.));
			loader.createBodyForCompoundShape(compound,false,trans,1.);
		}
	#endif
	m_dynamicsWorld = tmpW;
#else
	m_dynamicsWorld = m_pWorldI;
#endif//#ifdef SPHERES_DEMO


	clientResetScene();
#ifdef INTEGRATION_DEMO
	m_pWorldI->initDeviceData();
#endif

#ifdef SPHERES_DEMO
	m_pWorldS->initDeviceData();
#endif
	print_used_device();
}
Пример #25
0
void	BasicDemo3D::initPhysics()
{
	setTexturing(true);
	setShadows(false);

//	setCameraDistance(btScalar(SCALING*50.));
#if LARGE_DEMO
	setCameraDistance(btScalar(SCALING*50.));
#else
	setCameraDistance(btScalar(SCALING*20.));
#endif

	m_cameraTargetPosition.setValue(START_POS_X, -START_POS_Y-20, START_POS_Z);
	m_azi = btScalar(0.f);
	m_ele = btScalar(0.f);

	///collision configuration contains default setup for memory, collision setup

	btDefaultCollisionConstructionInfo dci;
	dci.m_defaultMaxPersistentManifoldPoolSize=100000;
	dci.m_defaultMaxCollisionAlgorithmPoolSize=100000;
	dci.m_customCollisionAlgorithmMaxElementSize = sizeof(SpuContactManifoldCollisionAlgorithm);	
	
	
	///SpuContactManifoldCollisionAlgorithm is larger than any of the other collision algorithms
//@@	dci.m_customMaxCollisionAlgorithmSize = sizeof(SpuContactManifoldCollisionAlgorithm);

	m_collisionConfiguration = new btDefaultCollisionConfiguration(dci);

	///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
	//m_dispatcher = new	btCollisionDispatcher(m_collisionConfiguration);
#ifndef WIN32
	m_dispatcher = new	btCollisionDispatcher(m_collisionConfiguration);
#else
	unsigned int	maxNumOutstandingTasks =4;
	//createCollisionLocalStoreMemory();
	//processSolverTask
	Win32ThreadSupport::Win32ThreadConstructionInfo  threadConstructionInfo("narrowphase_multi",processCollisionTask,createCollisionLocalStoreMemory,maxNumOutstandingTasks);
	class	btThreadSupportInterface*	threadInterface = new Win32ThreadSupport(threadConstructionInfo);
	m_dispatcher = new SpuGatheringCollisionDispatcher(threadInterface,maxNumOutstandingTasks,m_collisionConfiguration);
#endif //SINGLE_THREADED_NARROWPHASE


//##	m_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE,BOX_SHAPE_PROXYTYPE,new btEmptyAlgorithm::CreateFunc);
//##	m_dispatcher->registerCollisionCreateFunc(CUSTOM_CONVEX_SHAPE_TYPE,CUSTOM_CONVEX_SHAPE_TYPE,new btBox2dBox2dCollisionAlgorithm::CreateFunc);

//	m_broadphase = new btDbvtBroadphase();
	

//##	gPairCache = new (btAlignedAlloc(sizeof(btCudaDemoPairCache),16)) btCudaDemoPairCache(MAX_PROXIES, 24, MAX_SMALL_PROXIES); 
//	gPairCache = NULL;
	gPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); 

	//m_broadphase = new btSimpleBroadphase(16384, gPairCache);

/*
btCudaBroadphase::btCudaBroadphase(	btOverlappingPairCache* overlappingPairCache,
									const btVector3& worldAabbMin,const btVector3& worldAabbMax, 
									int gridSizeX, int gridSizeY, int gridSizeZ, 
									int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody,
									int maxBodiesPerCell,
									btScalar cellFactorAABB)
*/
	btScalar maxDiam = 1.76f * 2.0f * SCALING;  
	btVector3 cellSize(maxDiam, maxDiam, maxDiam);
	btVector3 numOfCells = (gWorldMax - gWorldMin) / cellSize;
	int numOfCellsX = btGpu3DGridBroadphase::getFloorPowOfTwo((int)numOfCells[0]);
	int numOfCellsY = btGpu3DGridBroadphase::getFloorPowOfTwo((int)numOfCells[1]);
	int numOfCellsZ = btGpu3DGridBroadphase::getFloorPowOfTwo((int)numOfCells[2]);
	m_broadphase = new bt3dGridBroadphaseOCL(gPairCache, cellSize,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,32,10.f, 32);

//	m_broadphase = new bt3dGridBroadphaseOCL(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,8,8,1./1.5);
//	m_broadphase = new btGpu3DGridBroadphaseOCL(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,8,8,1./1.5);
//	m_broadphase = new btGpu3DGridBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,8,8,1./1.5);
//#define USE_CUDA_BROADPHASE 1
#ifdef USE_CUDA_BROADPHASE
	m_broadphase = new btCudaBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,20,18,8,1./1.5);
#else
	
#if DBVT
	btDbvtBroadphase* dbvt = new btDbvtBroadphase(gPairCache);
	m_broadphase = dbvt;
	dbvt->m_deferedcollide=false;
	dbvt->m_prediction = 0.f;
#else
//	m_broadphase = new btAxisSweep3(gWorldMin,gWorldMax,32000,gPairCache,true);//(btDbvtBroadphase(gPairCache);
#endif //DBVT


#endif	
	


	// create solvers for tests 
	///the default constraint solver
	sConstraintSolvers[0] = new btSequentialImpulseConstraintSolver();
/*
	sConstraintSolvers[1] = new btParallelBatchConstraintSolver();
	sConstraintSolvers[2] = new btCudaConstraintSolver();
	sConstraintSolvers[3] = new btParallelBatchConstraintSolver2();
	sConstraintSolvers[4] = new btParallelBatchConstraintSolver3();
	sConstraintSolvers[5] = new btCudaConstraintSolver3();
	sConstraintSolvers[6] = new btParallelBatchConstraintSolver4();
	sConstraintSolvers[7] = new btCudaConstraintSolver4();
	sConstraintSolvers[8] = new btParallelBatchConstraintSolver5();
	sConstraintSolvers[9] = new btParallelBatchConstraintSolver6();
	sConstraintSolvers[10] = new btCudaConstraintSolver6();
*/
	sCurrSolverIndex = 0;
	m_solver = sConstraintSolvers[sCurrSolverIndex];
	printf("\nUsing %s\n", sConstraintSolverNames[sCurrSolverIndex]);

//	sCudaMotionInterface = new btCudaMotionInterface(MAX_PROXIES);
//  m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, sCudaMotionInterface);
//	m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
//##	btCudaDemoDynamicsWorld* pDdw = new btCudaDemoDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
	btCudaDemoDynamicsWorld3D* pDdw = new btCudaDemoDynamicsWorld3D(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
	m_pWorld = pDdw;
	m_dynamicsWorld = pDdw;
	pDdw->getDispatchInfo().m_enableSPU=true;
	pDdw->getSimulationIslandManager()->setSplitIslands(sCurrSolverIndex == 0);
	pDdw->setObjRad(SCALING);
	pDdw->setWorldMin(gWorldMin);
	pDdw->setWorldMax(gWorldMax);
//#ifdef BT_USE_CUDA
#if 1
	gUseCPUSolver = false;
#else
	gUseCPUSolver = true;
#endif
	pDdw->setUseCPUSolver(gUseCPUSolver);
//	pDdw->setUseSolver2(gUseSolver2);

//	m_dynamicsWorld->setGravity(btVector3(0,0,0));
	m_dynamicsWorld->setGravity(btVector3(0.f,-10.f,0.f));
	m_dynamicsWorld->getSolverInfo().m_numIterations = 4;


	{
		//create a few dynamic rigidbodies
		// Re-using the same collision is better for memory usage and performance


		//btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,0.1));//SCALING*1));
//##		btCollisionShape* colShape = new btBox2dShape(btVector3(SCALING*.7,SCALING*.7,0.1));//SCALING*1));
		btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*.7,SCALING*.7, SCALING*.7));

		//btCollisionShape* colShape = new btSphereShape(btScalar(1.));
		m_collisionShapes.push_back(colShape);

		/// Create Dynamic Objects
		btTransform startTransform;
		startTransform.setIdentity();

		btScalar	mass(1.f);

		//rigidbody is dynamic if and only if mass is non zero, otherwise static
		bool isDynamic = (mass != 0.f);

		btVector3 localInertia(0,0,0);
		if (isDynamic)
			colShape->calculateLocalInertia(mass,localInertia);
#if (!SPEC_TEST)
		float start_x = START_POS_X - ARRAY_SIZE_X * SCALING;
		float start_y = START_POS_Y - ARRAY_SIZE_Y * SCALING;
		float start_z = START_POS_Z - ARRAY_SIZE_Z * SCALING;

		for (int k=0;k<ARRAY_SIZE_Y;k++)
		{
			for (int i=0;i<ARRAY_SIZE_X;i++)
			{
				for(int j = 0;j<ARRAY_SIZE_Z;j++)
				{
					startTransform.setOrigin(SCALING*btVector3(
										2.0*SCALING*i + start_x,
										2.0*SCALING*k + start_y,
										2.0*SCALING*j + start_z));

			
					//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
					//btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
					btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia);
					rbInfo.m_startWorldTransform=startTransform;
					btRigidBody* body = new btRigidBody(rbInfo);
					m_dynamicsWorld->addRigidBody(body);
				}
			}
		}
#else
		// narrowphase test - 2 bodies at the same position
		float start_x = START_POS_X;
		float start_y = START_POS_Y;
		float start_z = START_POS_Z;
//		startTransform.setOrigin(SCALING*btVector3(start_x,start_y-14.f,start_z));
		startTransform.setOrigin(SCALING*btVector3(start_x,start_y-11.f,start_z));
		btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia);
		rbInfo.m_startWorldTransform=startTransform;
		btRigidBody* body = new btRigidBody(rbInfo);
		m_dynamicsWorld->addRigidBody(body);
//		startTransform.setOrigin(SCALING*btVector3(start_x+1.2f,start_y+1.4f-14.f,start_z));
		startTransform.setOrigin(SCALING*btVector3(start_x,start_y + 1.5f -11.f, start_z));
		rbInfo.m_startWorldTransform=startTransform;
		body = new btRigidBody(rbInfo);
		m_dynamicsWorld->addRigidBody(body);
#endif
	}


#if 0
	///create a few basic rigid bodies
//	btCollisionShape* groundShape = new btBox2dShape(btVector3(btScalar(50.),btScalar(1.),btScalar(50.)));
//	btCollisionShape* groundShape = new btBox2dShape(btVector3(btScalar(228.),btScalar(1.),btScalar(228.)));
//	btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(228.),btScalar(1.),btScalar(228.)));
//	btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
//	btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50);
	btCollisionShape* groundShape = new btBoxShape(btVector3(POS_OFFS_X, btScalar(1.), POS_OFFS_Z));
	
	m_collisionShapes.push_back(groundShape);

	btTransform groundTransform;
	groundTransform.setIdentity();
	groundTransform.setOrigin(btVector3(0, gWorldMin[1], 0));

//	groundTransform.setOrigin(btVector3(0,-5,0));
//	groundTransform.setOrigin(btVector3(0,-50,0));

	//We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
	{
		btScalar mass(0.);

		//rigidbody is dynamic if and only if mass is non zero, otherwise static
		bool isDynamic = (mass != 0.f);

		btVector3 localInertia(0,0,0);
		if (isDynamic)
			groundShape->calculateLocalInertia(mass,localInertia);

		//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
		btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
		btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
		btRigidBody* body = new btRigidBody(rbInfo);

		//add the body to the dynamics world
		m_dynamicsWorld->addRigidBody(body);
	}
#endif
	//clientResetScene();
}
Пример #26
0
/** Creates a collision body only, which can be used for raycasting, but
 *  has no physical properties.
 *  @param serialized_bhv if non-null, load the serialized bhv from file instead
 *                        of builing it on the fly
 */
void TriangleMesh::createCollisionShape(bool create_collision_object, const char* serialized_bhv)
{
    if(m_triangleIndex2Material.size()==0)
    {
        m_collision_shape  = NULL;
        m_motion_state     = NULL;
        m_body             = NULL;
        m_collision_object = NULL;
        return;
    }
    // Now convert the triangle mesh into a static rigid body
    btBvhTriangleMeshShape* bhv_triangle_mesh;

    if (serialized_bhv != NULL)
    {
        FILE *f = fopen(serialized_bhv, "rb");
        fseek(f, 0, SEEK_END);
        long pos = ftell(f);
        assert(pos != -1L);
        fseek(f, 0, SEEK_SET);

        void* bytes = btAlignedAlloc(pos, 16);
        fread(bytes, pos, 1, f);
        fclose(f);

        btOptimizedBvh* bhv = btOptimizedBvh::deSerializeInPlace(bytes, pos, !IS_LITTLE_ENDIAN);
        if (bhv == NULL)
        {
            Log::warn("TriangleMesh", "Failed to load serialized BHV");
            bhv_triangle_mesh = new btBvhTriangleMeshShape(&m_mesh, false /* useQuantizedAabbCompression */);
        }
        else
        {
            bhv_triangle_mesh = new btBvhTriangleMeshShape(&m_mesh, false /* useQuantizedAabbCompression */,
                                                           false /* buildBvh */);
            bhv_triangle_mesh->setOptimizedBvh( bhv );
        }
        // Do *NOT* free the bytes, 'deSerializeInPlace' makes the btOptimizedBvh object
        // directly at this memory location
        //free(bytes);

    }
    else
    {
        bhv_triangle_mesh = new btBvhTriangleMeshShape(&m_mesh, false /* useQuantizedAabbCompression */);

        /*
         // code to serialize triangle mesh
        btOptimizedBvh* bvh = bhv_triangle_mesh->getOptimizedBvh();
        unsigned int ssize = bvh->calculateSerializeBufferSize();
        char* buffer = (char*)btAlignedAlloc(ssize, 16);
        bool success = bvh->serialize(buffer, ssize, !IS_LITTLE_ENDIAN);
        printf("serialization success = %i\n", success);

        std::ofstream fileout("/tmp/btOptimizedBvh");
        fileout.write(buffer, ssize);
        fileout.close();

        btAlignedFree(buffer);
         */
    }

    m_collision_shape = bhv_triangle_mesh;
    m_collision_shape->setUserPointer(&m_user_pointer);
    if(create_collision_object)
    {
        m_collision_object = new btCollisionObject();
        btTransform bt;
        bt.setIdentity();
        m_collision_object->setWorldTransform(bt);
    }


}   // createCollisionShape
void btGpu3DGridBroadphase::_initialize(	const btVector3& worldAabbMin,const btVector3& worldAabbMax, 
										int gridSizeX, int gridSizeY, int gridSizeZ, 
										int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody,
										int maxBodiesPerCell,
										btScalar cellFactorAABB)
{
	// set various paramerers
	m_ownsPairCache = true;
	m_params.m_gridSizeX = gridSizeX;
	m_params.m_gridSizeY = gridSizeY;
	m_params.m_gridSizeZ = gridSizeZ;
	m_params.m_numCells = m_params.m_gridSizeX * m_params.m_gridSizeY * m_params.m_gridSizeZ;
	btVector3 w_org = worldAabbMin;
	m_params.m_worldOriginX = w_org.getX();
	m_params.m_worldOriginY = w_org.getY();
	m_params.m_worldOriginZ = w_org.getZ();
	btVector3 w_size = worldAabbMax - worldAabbMin;
	m_params.m_cellSizeX = w_size.getX() / m_params.m_gridSizeX;
	m_params.m_cellSizeY = w_size.getY() / m_params.m_gridSizeY;
	m_params.m_cellSizeZ = w_size.getZ() / m_params.m_gridSizeZ;
	m_maxRadius = btMin(btMin(m_params.m_cellSizeX, m_params.m_cellSizeY), m_params.m_cellSizeZ);
	m_maxRadius *= btScalar(0.5f);
	m_params.m_numBodies = m_numBodies;
	m_params.m_maxBodiesPerCell = maxBodiesPerCell;

	m_numLargeHandles = 0;						
	m_maxLargeHandles = maxLargeProxies;

	m_maxPairsPerBody = maxPairsPerBody;

	m_cellFactorAABB = cellFactorAABB;

	m_LastLargeHandleIndex = -1;

    btAssert(!m_bInitialized);
    // allocate host storage
    m_hBodiesHash = new unsigned int[m_maxHandles * 2];
    memset(m_hBodiesHash, 0x00, m_maxHandles*2*sizeof(unsigned int));

    m_hCellStart = new unsigned int[m_params.m_numCells];
    memset(m_hCellStart, 0x00, m_params.m_numCells * sizeof(unsigned int));

	m_hPairBuffStartCurr = new unsigned int[m_maxHandles * 2 + 2];
	// --------------- for now, init with m_maxPairsPerBody for each body
	m_hPairBuffStartCurr[0] = 0;
	m_hPairBuffStartCurr[1] = 0;
	for(int i = 1; i <= m_maxHandles; i++) 
	{
		m_hPairBuffStartCurr[i * 2] = m_hPairBuffStartCurr[(i-1) * 2] + m_maxPairsPerBody;
		m_hPairBuffStartCurr[i * 2 + 1] = 0;
	}
	//----------------
	unsigned int numAABB = m_maxHandles + m_maxLargeHandles;
	m_hAABB = new bt3DGrid3F1U[numAABB * 2]; // AABB Min & Max

	m_hPairBuff = new unsigned int[m_maxHandles * m_maxPairsPerBody];
	memset(m_hPairBuff, 0x00, m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int)); // needed?

	m_hPairScan = new unsigned int[m_maxHandles + 1];

	m_hPairOut = new unsigned int[m_maxHandles * m_maxPairsPerBody];

// large proxies

	// allocate handles buffer and put all handles on free list
	m_pLargeHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy) * m_maxLargeHandles, 16);
	m_pLargeHandles = new(m_pLargeHandlesRawPtr) btSimpleBroadphaseProxy[m_maxLargeHandles];
	m_firstFreeLargeHandle = 0;
	{
		for (int i = m_firstFreeLargeHandle; i < m_maxLargeHandles; i++)
		{
			m_pLargeHandles[i].SetNextFree(i + 1);
			m_pLargeHandles[i].m_uniqueId = m_maxHandles+2+i;
		}
		m_pLargeHandles[m_maxLargeHandles - 1].SetNextFree(0);
	}

// debug data
	m_numPairsAdded = 0;
	m_numOverflows = 0;

    m_bInitialized = true;
}
Пример #28
0
	virtual bool convertAllObjects(  bParse::btBulletFile* bulletFile2)
	{
		bool result = btBulletWorldImporter::convertAllObjects(bulletFile2);
		int i;
		//now the soft bodies
		for (i=0;i<bulletFile2->m_softBodies.size();i++)
		{
			if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
			{
				btAssert(0); //not yet
				//btSoftBodyFloatData* softBodyData = (btSoftBodyFloatData*)bulletFile2->m_softBodies[i];
			} else
			{
				btSoftBodyFloatData* softBodyData = (btSoftBodyFloatData*)bulletFile2->m_softBodies[i];
				int i;
				int numNodes = softBodyData->m_numNodes;
				
		
				btSoftBody*		psb=new btSoftBody(&m_softRigidWorld->getWorldInfo());
				m_softBodyMap.insert(softBodyData,psb);

				//materials
				for (i=0;i<softBodyData->m_numMaterials;i++)
				{
					SoftBodyMaterialData* matData = softBodyData->m_materials[i];
					btSoftBody::Material** matPtr = m_materialMap.find(matData);
					btSoftBody::Material* mat = 0;
					if (matPtr&& *matPtr)
					{
						mat = *matPtr;
					} else
					{
						mat = psb->appendMaterial();
						mat->m_flags = matData->m_flags;
						mat->m_kAST = matData->m_angularStiffness;
						mat->m_kLST = matData->m_linearStiffness;
						mat->m_kVST = matData->m_volumeStiffness;
						m_materialMap.insert(matData,mat);
					}
				}




				for (i=0;i<numNodes;i++)
				{
					SoftBodyNodeData& nodeData = softBodyData->m_nodes[i];
					btVector3 position;
					position.deSerializeFloat(nodeData.m_position);
					btScalar mass = nodeData.m_inverseMass? 1./nodeData.m_inverseMass : 0.f;
					psb->appendNode(position,mass);
					btSoftBody::Node* node = &psb->m_nodes[psb->m_nodes.size()-1];
					node->m_area = nodeData.m_area;
					node->m_battach = nodeData.m_attach;
					node->m_f.deSerializeFloat(nodeData.m_accumulatedForce);
					node->m_im = nodeData.m_inverseMass;

					btSoftBody::Material** matPtr = m_materialMap.find(nodeData.m_material);
					if (matPtr && *matPtr)
					{
						node->m_material = *matPtr;
					} else
					{
						printf("no mat?\n");
					}
					
					node->m_n.deSerializeFloat(nodeData.m_normal);
					node->m_q = node->m_x;
					node->m_v.deSerializeFloat(nodeData.m_velocity);
					
				}

				for (i=0;i<softBodyData->m_numLinks;i++)
				{
					SoftBodyLinkData& linkData = softBodyData->m_links[i];
					btSoftBody::Material** matPtr = m_materialMap.find(linkData.m_material);
					if (matPtr && *matPtr)
					{
						psb->appendLink(linkData.m_nodeIndices[0],linkData.m_nodeIndices[1],*matPtr);
					} else
					{
						psb->appendLink(linkData.m_nodeIndices[0],linkData.m_nodeIndices[1]);
					}
					btSoftBody::Link* link = &psb->m_links[psb->m_links.size()-1];
					link->m_bbending = linkData.m_bbending;
					link->m_rl = linkData.m_restLength;
				}

				for (i=0;i<softBodyData->m_numFaces;i++)
				{
					SoftBodyFaceData& faceData = softBodyData->m_faces[i];
					btSoftBody::Material** matPtr = m_materialMap.find(faceData.m_material);
					if (matPtr && *matPtr)
					{
						psb->appendFace(faceData.m_nodeIndices[0],faceData.m_nodeIndices[1],faceData.m_nodeIndices[2],*matPtr);
					} else
					{
						psb->appendFace(faceData.m_nodeIndices[0],faceData.m_nodeIndices[1],faceData.m_nodeIndices[2]);
					}
					btSoftBody::Face* face = &psb->m_faces[psb->m_faces.size()-1];
					face->m_normal.deSerializeFloat(faceData.m_normal);
					face->m_ra = faceData.m_restArea;
				}

			

				//anchors
				for (i=0;i<softBodyData->m_numAnchors;i++)
				{
					btCollisionObject** colAptr = m_bodyMap.find(softBodyData->m_anchors[i].m_rigidBody);
					if (colAptr && *colAptr)
					{
						btRigidBody* body = btRigidBody::upcast(*colAptr);
						if (body)
						{
							bool disableCollision = false;
							btVector3 localPivot;
							localPivot.deSerializeFloat(softBodyData->m_anchors[i].m_localFrame);
							psb->appendAnchor(softBodyData->m_anchors[i].m_nodeIndex,body,localPivot, disableCollision);
						}
					}
				}

				if (softBodyData->m_pose)
				{
					psb->m_pose.m_aqq.deSerializeFloat(  softBodyData->m_pose->m_aqq);
					psb->m_pose.m_bframe = (softBodyData->m_pose->m_bframe!=0);
					psb->m_pose.m_bvolume = (softBodyData->m_pose->m_bvolume!=0);
					psb->m_pose.m_com.deSerializeFloat(softBodyData->m_pose->m_com);
					
					psb->m_pose.m_pos.resize(softBodyData->m_pose->m_numPositions);
					for (i=0;i<softBodyData->m_pose->m_numPositions;i++)
					{
						psb->m_pose.m_pos[i].deSerializeFloat(softBodyData->m_pose->m_positions[i]);
					}
					psb->m_pose.m_rot.deSerializeFloat(softBodyData->m_pose->m_rot);
					psb->m_pose.m_scl.deSerializeFloat(softBodyData->m_pose->m_scale);
					psb->m_pose.m_wgh.resize(softBodyData->m_pose->m_numWeigts);
					for (i=0;i<softBodyData->m_pose->m_numWeigts;i++)
					{
						psb->m_pose.m_wgh[i] = softBodyData->m_pose->m_weights[i];
					}
					psb->m_pose.m_volume = softBodyData->m_pose->m_restVolume;
				}

#if 1
				psb->m_cfg.piterations=softBodyData->m_config.m_positionIterations;
				psb->m_cfg.diterations=softBodyData->m_config.m_driftIterations;
				psb->m_cfg.citerations=softBodyData->m_config.m_clusterIterations;
				psb->m_cfg.viterations=softBodyData->m_config.m_velocityIterations;
				
				//psb->setTotalMass(0.1);
				psb->m_cfg.aeromodel = (btSoftBody::eAeroModel::_)softBodyData->m_config.m_aeroModel;
				psb->m_cfg.kLF = softBodyData->m_config.m_lift;
				psb->m_cfg.kDG = softBodyData->m_config.m_drag;
				psb->m_cfg.kMT = softBodyData->m_config.m_poseMatch;
				psb->m_cfg.collisions = softBodyData->m_config.m_collisionFlags;
				psb->m_cfg.kDF = 1.f;//softBodyData->m_config.m_dynamicFriction;
				psb->m_cfg.kDP = softBodyData->m_config.m_damping;
				psb->m_cfg.kPR = softBodyData->m_config.m_pressure;
				psb->m_cfg.kVC = softBodyData->m_config.m_volume;
				psb->m_cfg.kAHR = softBodyData->m_config.m_anchorHardness;
				psb->m_cfg.kKHR = softBodyData->m_config.m_kineticContactHardness;
				psb->m_cfg.kSHR = softBodyData->m_config.m_softContactHardness;
				psb->m_cfg.kSRHR_CL = softBodyData->m_config.m_softRigidClusterHardness;
				psb->m_cfg.kSKHR_CL = softBodyData->m_config.m_softKineticClusterHardness;
				psb->m_cfg.kSSHR_CL = softBodyData->m_config.m_softSoftClusterHardness;
#endif

//				pm->m_kLST				=	1;

#if 1
				//clusters
				if (softBodyData->m_numClusters)
				{
					m_clusterBodyMap.insert(softBodyData->m_clusters,psb);
					int j;
					psb->m_clusters.resize(softBodyData->m_numClusters);
					for (i=0;i<softBodyData->m_numClusters;i++)
					{
						psb->m_clusters[i] = new(btAlignedAlloc(sizeof(btSoftBody::Cluster),16)) btSoftBody::Cluster();
						psb->m_clusters[i]->m_adamping = softBodyData->m_clusters[i].m_adamping;
						psb->m_clusters[i]->m_av.deSerializeFloat(softBodyData->m_clusters[i].m_av);
						psb->m_clusters[i]->m_clusterIndex = softBodyData->m_clusters[i].m_clusterIndex;
						psb->m_clusters[i]->m_collide = (softBodyData->m_clusters[i].m_collide!=0);
						psb->m_clusters[i]->m_com.deSerializeFloat(softBodyData->m_clusters[i].m_com);
						psb->m_clusters[i]->m_containsAnchor = (softBodyData->m_clusters[i].m_containsAnchor!=0);
						psb->m_clusters[i]->m_dimpulses[0].deSerializeFloat(softBodyData->m_clusters[i].m_dimpulses[0]);
						psb->m_clusters[i]->m_dimpulses[1].deSerializeFloat(softBodyData->m_clusters[i].m_dimpulses[1]);

						psb->m_clusters[i]->m_framerefs.resize(softBodyData->m_clusters[i].m_numFrameRefs);
						for (j=0;j<softBodyData->m_clusters[i].m_numFrameRefs;j++)
						{
							psb->m_clusters[i]->m_framerefs[j].deSerializeFloat(softBodyData->m_clusters[i].m_framerefs[j]);
						}
						psb->m_clusters[i]->m_nodes.resize(softBodyData->m_clusters[i].m_numNodes);
						for (j=0;j<softBodyData->m_clusters[i].m_numNodes;j++)
						{
							int nodeIndex = softBodyData->m_clusters[i].m_nodeIndices[j];
							psb->m_clusters[i]->m_nodes[j] = &psb->m_nodes[nodeIndex];
						}

						psb->m_clusters[i]->m_masses.resize(softBodyData->m_clusters[i].m_numMasses);
						for (j=0;j<softBodyData->m_clusters[i].m_numMasses;j++)
						{
							psb->m_clusters[i]->m_masses[j] = softBodyData->m_clusters[i].m_masses[j];
						}
						psb->m_clusters[i]->m_framexform.deSerializeFloat(softBodyData->m_clusters[i].m_framexform);
						psb->m_clusters[i]->m_idmass = softBodyData->m_clusters[i].m_idmass;
						psb->m_clusters[i]->m_imass = softBodyData->m_clusters[i].m_imass;
						psb->m_clusters[i]->m_invwi.deSerializeFloat(softBodyData->m_clusters[i].m_invwi);
						psb->m_clusters[i]->m_ldamping = softBodyData->m_clusters[i].m_ldamping;
						psb->m_clusters[i]->m_locii.deSerializeFloat(softBodyData->m_clusters[i].m_locii);
						psb->m_clusters[i]->m_lv.deSerializeFloat(softBodyData->m_clusters[i].m_lv);
						psb->m_clusters[i]->m_matching = softBodyData->m_clusters[i].m_matching;
						psb->m_clusters[i]->m_maxSelfCollisionImpulse = 0;//softBodyData->m_clusters[i].m_maxSelfCollisionImpulse;
						psb->m_clusters[i]->m_ndamping = softBodyData->m_clusters[i].m_ndamping;
						psb->m_clusters[i]->m_ndimpulses = softBodyData->m_clusters[i].m_ndimpulses;
						psb->m_clusters[i]->m_nvimpulses = softBodyData->m_clusters[i].m_nvimpulses;
						psb->m_clusters[i]->m_selfCollisionImpulseFactor = softBodyData->m_clusters[i].m_selfCollisionImpulseFactor;
						psb->m_clusters[i]->m_vimpulses[0].deSerializeFloat(softBodyData->m_clusters[i].m_vimpulses[0]);
						psb->m_clusters[i]->m_vimpulses[1].deSerializeFloat(softBodyData->m_clusters[i].m_vimpulses[1]);
						
					}
					//psb->initializeClusters();
					//psb->updateClusters();

				}
#else

				psb->m_cfg.piterations	=	2;
				psb->m_cfg.collisions	=	btSoftBody::fCollision::CL_SS+	btSoftBody::fCollision::CL_RS;
				//psb->setTotalMass(50,true);
				//psb->generateClusters(64);
				//psb->m_cfg.kDF=1;
				psb->generateClusters(8);


#endif //



				psb->updateConstants();
				m_softRigidWorld->getWorldInfo().m_dispatcher = m_softRigidWorld->getDispatcher();
				
				m_softRigidWorld->addSoftBody(psb);


			}
		}


		//now the soft body joints
		for (i=0;i<bulletFile2->m_softBodies.size();i++)
		{
			if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
			{
				btAssert(0); //not yet
				//btSoftBodyFloatData* softBodyData = (btSoftBodyFloatData*)bulletFile2->m_softBodies[i];
			} else
			{
				btSoftBodyFloatData* softBodyData = (btSoftBodyFloatData*)bulletFile2->m_softBodies[i];
				btSoftBody** sbp = m_softBodyMap.find(softBodyData);
				if (sbp && *sbp)
				{
					btSoftBody* sb = *sbp;
					for (int i=0;i<softBodyData->m_numJoints;i++)
					{
						btSoftBodyJointData* sbjoint = &softBodyData->m_joints[i];


						btSoftBody::Body bdyB;

						btSoftBody* sbB = 0;
						btTransform transA;
						transA.setIdentity();
						transA = sb->m_clusters[0]->m_framexform;

						btCollisionObject** colBptr = m_bodyMap.find(sbjoint->m_bodyB);
						if (colBptr && *colBptr)
						{
							btRigidBody* rbB = btRigidBody::upcast(*colBptr);
							if (rbB)
							{
								bdyB = rbB;
							} else
							{
								bdyB = *colBptr;
							}
						}


						btSoftBody** bodyBptr = m_clusterBodyMap.find(sbjoint->m_bodyB);
						if (bodyBptr && *bodyBptr )
						{
							sbB = *bodyBptr;
							bdyB = sbB->m_clusters[0];
						}


						if (sbjoint->m_jointType==btSoftBody::Joint::eType::Linear)
						{
							btSoftBody::LJoint::Specs specs;
							specs.cfm = sbjoint->m_cfm;
							specs.erp = sbjoint->m_erp;
							specs.split = sbjoint->m_split;
							btVector3 relA;
							relA.deSerializeFloat(sbjoint->m_refs[0]);
							specs.position = transA*relA;
							sb->appendLinearJoint(specs,sb->m_clusters[0],bdyB);
						}

						if (sbjoint->m_jointType==btSoftBody::Joint::eType::Angular)
						{
							btSoftBody::AJoint::Specs specs;
							specs.cfm = sbjoint->m_cfm;
							specs.erp = sbjoint->m_erp;
							specs.split = sbjoint->m_split;
							btVector3 relA;
							relA.deSerializeFloat(sbjoint->m_refs[0]);
							specs.axis = transA.getBasis()*relA;
							sb->appendAngularJoint(specs,sb->m_clusters[0],bdyB);
						}
					}
				}

			}
		}

		return result;

	}
bool	btPolyhedralConvexShape::initializePolyhedralFeatures()
{

	if (m_polyhedron)
		btAlignedFree(m_polyhedron);
	
	void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16);
	m_polyhedron = new (mem) btConvexPolyhedron;

		btAlignedObjectArray<btVector3> orgVertices;

	for (int i=0;i<getNumVertices();i++)
	{
		btVector3& newVertex = orgVertices.expand();
		getVertex(i,newVertex);
	}

#if 0
	btAlignedObjectArray<btVector3> planeEquations;
	btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations);

	btAlignedObjectArray<btVector3> shiftedPlaneEquations;
	for (int p=0;p<planeEquations.size();p++)
	{
		   btVector3 plane = planeEquations[p];
		   plane[3] -= getMargin();
		   shiftedPlaneEquations.push_back(plane);
	}

	btAlignedObjectArray<btVector3> tmpVertices;

	btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices);
	btConvexHullComputer conv;
	conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f);

#else
	btConvexHullComputer conv;
	conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f);

#endif



	btAlignedObjectArray<btVector3> faceNormals;
	int numFaces = conv.faces.size();
	faceNormals.resize(numFaces);
	btConvexHullComputer* convexUtil = &conv;

	
	btAlignedObjectArray<btFace>	tmpFaces;
	tmpFaces.resize(numFaces);

	int numVertices = convexUtil->vertices.size();
	m_polyhedron->m_vertices.resize(numVertices);
	for (int p=0;p<numVertices;p++)
	{
		m_polyhedron->m_vertices[p] = convexUtil->vertices[p];
	}


	for (int i=0;i<numFaces;i++)
	{
		int face = convexUtil->faces[i];
		//printf("face=%d\n",face);
		const btConvexHullComputer::Edge*  firstEdge = &convexUtil->edges[face];
		const btConvexHullComputer::Edge*  edge = firstEdge;

		btVector3 edges[3];
		int numEdges = 0;
		//compute face normals

		btScalar maxCross2 = 0.f;
		int chosenEdge = -1;

		do
		{
			
			int src = edge->getSourceVertex();
			tmpFaces[i].m_indices.push_back(src);
			int targ = edge->getTargetVertex();
			btVector3 wa = convexUtil->vertices[src];

			btVector3 wb = convexUtil->vertices[targ];
			btVector3 newEdge = wb-wa;
			newEdge.normalize();
			if (numEdges<2)
				edges[numEdges++] = newEdge;

			edge = edge->getNextEdgeOfFace();
		} while (edge!=firstEdge);

		btScalar planeEq = 1e30f;

		
		if (numEdges==2)
		{
			faceNormals[i] = edges[0].cross(edges[1]);
			faceNormals[i].normalize();
			tmpFaces[i].m_plane[0] = faceNormals[i].getX();
			tmpFaces[i].m_plane[1] = faceNormals[i].getY();
			tmpFaces[i].m_plane[2] = faceNormals[i].getZ();
			tmpFaces[i].m_plane[3] = planeEq;

		}
		else
		{
			btAssert(0);//degenerate?
			faceNormals[i].setZero();
		}

		for (int v=0;v<tmpFaces[i].m_indices.size();v++)
		{
			btScalar eq = m_polyhedron->m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]);
			if (planeEq>eq)
			{
				planeEq=eq;
			}
		}
		tmpFaces[i].m_plane[3] = -planeEq;
	}

	//merge coplanar faces and copy them to m_polyhedron

	btScalar faceWeldThreshold= 0.999f;
	btAlignedObjectArray<int> todoFaces;
	for (int i=0;i<tmpFaces.size();i++)
		todoFaces.push_back(i);

	while (todoFaces.size())
	{
		btAlignedObjectArray<int> coplanarFaceGroup;
		int refFace = todoFaces[todoFaces.size()-1];

		coplanarFaceGroup.push_back(refFace);
		btFace& faceA = tmpFaces[refFace];
		todoFaces.pop_back();

		btVector3 faceNormalA(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]);
		for (int j=todoFaces.size()-1;j>=0;j--)
		{
			int i = todoFaces[j];
			btFace& faceB = tmpFaces[i];
			btVector3 faceNormalB(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]);
			if (faceNormalA.dot(faceNormalB)>faceWeldThreshold)
			{
				coplanarFaceGroup.push_back(i);
				todoFaces.remove(i);
			}
		}


		bool did_merge = false;
		if (coplanarFaceGroup.size()>1)
		{
			//do the merge: use Graham Scan 2d convex hull

			btAlignedObjectArray<GrahamVector2> orgpoints;

			for (int i=0;i<coplanarFaceGroup.size();i++)
			{
//				m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);

				btFace& face = tmpFaces[coplanarFaceGroup[i]];
				btVector3 faceNormal(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
				btVector3 xyPlaneNormal(0,0,1);

				btQuaternion rotationArc = shortestArcQuat(faceNormal,xyPlaneNormal);
				
				for (int f=0;f<face.m_indices.size();f++)
				{
					int orgIndex = face.m_indices[f];
					btVector3 pt = m_polyhedron->m_vertices[orgIndex];
					btVector3 rotatedPt =  quatRotate(rotationArc,pt);
					rotatedPt.setZ(0);
					bool found = false;

					for (int i=0;i<orgpoints.size();i++)
					{
						//if ((orgpoints[i].m_orgIndex == orgIndex) || ((rotatedPt-orgpoints[i]).length2()<0.0001))
						if (orgpoints[i].m_orgIndex == orgIndex)
						{
							found=true;
							break;
						}
					}
					if (!found)
						orgpoints.push_back(GrahamVector2(rotatedPt,orgIndex));
				}
			}

			btFace combinedFace;
			for (int i=0;i<4;i++)
				combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];

			btAlignedObjectArray<GrahamVector2> hull;
			GrahamScanConvexHull2D(orgpoints,hull);

			for (int i=0;i<hull.size();i++)
			{
				combinedFace.m_indices.push_back(hull[i].m_orgIndex);
				for(int k = 0; k < orgpoints.size(); k++) {
					if(orgpoints[k].m_orgIndex == hull[i].m_orgIndex) {
						orgpoints[k].m_orgIndex = -1; // invalidate...
						break;
			}
				}
			}
			// are there rejected vertices?
			bool reject_merge = false;
			for(int i = 0; i < orgpoints.size(); i++) {
				if(orgpoints[i].m_orgIndex == -1)
					continue; // this is in the hull...
				// this vertex is rejected -- is anybody else using this vertex?
				for(int j = 0; j < tmpFaces.size(); j++) {
					btFace& face = tmpFaces[j];
					// is this a face of the current coplanar group?
					bool is_in_current_group = false;
					for(int k = 0; k < coplanarFaceGroup.size(); k++) {
						if(coplanarFaceGroup[k] == j) {
							is_in_current_group = true;
							break;
						}
					}
					if(is_in_current_group) // ignore this face...
						continue;
					// does this face use this rejected vertex?
					for(int v = 0; v < face.m_indices.size(); v++) {
						if(face.m_indices[v] == orgpoints[i].m_orgIndex) {
							// this rejected vertex is used in another face -- reject merge
							reject_merge = true;
							break;
						}
					}
					if(reject_merge)
						break;
				}
				if(reject_merge)
					break;
			}
			if(!reject_merge) {
				// do this merge!
				did_merge = true;
			m_polyhedron->m_faces.push_back(combinedFace);
			}
		}
		if(!did_merge)
		{
			for (int i=0;i<coplanarFaceGroup.size();i++)
			{
				m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
			}

		}



	}
	
	m_polyhedron->initialize();

	return true;
}
bool	btPolyhedralConvexShape::initializePolyhedralFeatures()
{
	if (m_polyhedron)
		btAlignedFree(m_polyhedron);
	
	void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16);
	m_polyhedron = new (mem) btConvexPolyhedron;

	btAlignedObjectArray<btVector3> tmpVertices;
	for (int i=0;i<getNumVertices();i++)
	{
		btVector3& newVertex = tmpVertices.expand();
		getVertex(i,newVertex);
	}

	btConvexHullComputer conv;
	conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f);

	

	btAlignedObjectArray<btVector3> faceNormals;
	int numFaces = conv.faces.size();
	faceNormals.resize(numFaces);
	btConvexHullComputer* convexUtil = &conv;

	
	
	m_polyhedron->m_faces.resize(numFaces);
	int numVertices = convexUtil->vertices.size();
	m_polyhedron->m_vertices.resize(numVertices);
	for (int p=0;p<numVertices;p++)
	{
		m_polyhedron->m_vertices[p] = convexUtil->vertices[p];
	}

	for (int i=0;i<numFaces;i++)
	{
		int face = convexUtil->faces[i];
		//printf("face=%d\n",face);
		const btConvexHullComputer::Edge*  firstEdge = &convexUtil->edges[face];
		const btConvexHullComputer::Edge*  edge = firstEdge;

		btVector3 edges[3];
		int numEdges = 0;
		//compute face normals

		//btScalar maxCross2 = 0.f;
		//int chosenEdge = -1;

		do
		{
			
			int src = edge->getSourceVertex();
			m_polyhedron->m_faces[i].m_indices.push_back(src);
			int targ = edge->getTargetVertex();
			btVector3 wa = convexUtil->vertices[src];

			btVector3 wb = convexUtil->vertices[targ];
			btVector3 newEdge = wb-wa;
			newEdge.normalize();
			if (numEdges<2)
				edges[numEdges++] = newEdge;

			edge = edge->getNextEdgeOfFace();
		} while (edge!=firstEdge);

		btScalar planeEq = 1e30f;

		
		if (numEdges==2)
		{
			faceNormals[i] = edges[0].cross(edges[1]);
			faceNormals[i].normalize();
			m_polyhedron->m_faces[i].m_plane[0] = -faceNormals[i].getX();
			m_polyhedron->m_faces[i].m_plane[1] = -faceNormals[i].getY();
			m_polyhedron->m_faces[i].m_plane[2] = -faceNormals[i].getZ();
			m_polyhedron->m_faces[i].m_plane[3] = planeEq;

		}
		else
		{
			btAssert(0);//degenerate?
			faceNormals[i].setZero();
		}

		for (int v=0;v<m_polyhedron->m_faces[i].m_indices.size();v++)
		{
			btScalar eq = m_polyhedron->m_vertices[m_polyhedron->m_faces[i].m_indices[v]].dot(faceNormals[i]);
			if (planeEq>eq)
			{
				planeEq=eq;
			}
		}
		m_polyhedron->m_faces[i].m_plane[3] = planeEq;
	}


	if (m_polyhedron->m_faces.size() && conv.vertices.size())
	{

		for (int f=0;f<m_polyhedron->m_faces.size();f++)
		{
			
			btVector3 planeNormal(m_polyhedron->m_faces[f].m_plane[0],m_polyhedron->m_faces[f].m_plane[1],m_polyhedron->m_faces[f].m_plane[2]);
			btScalar planeEq = m_polyhedron->m_faces[f].m_plane[3];

			btVector3 supVec = localGetSupportingVertex(-planeNormal);

			if (supVec.dot(planeNormal)<planeEq)
			{
				m_polyhedron->m_faces[f].m_plane[0] *= -1;
				m_polyhedron->m_faces[f].m_plane[1] *= -1;
				m_polyhedron->m_faces[f].m_plane[2] *= -1;
				m_polyhedron->m_faces[f].m_plane[3] *= -1;
				int numVerts = m_polyhedron->m_faces[f].m_indices.size();
				for (int v=0;v<numVerts/2;v++)
				{
					btSwap(m_polyhedron->m_faces[f].m_indices[v],m_polyhedron->m_faces[f].m_indices[numVerts-1-v]);
				}
			}
		}
	}

	

	m_polyhedron->initialize();

	return true;
}