PhysX和Box2D 性能对比

梦想游戏人
目录:
未分类

结论1:简单模拟下 刚体数量比较多的情况下 PhysX 性能高很多,反之Box2D性能高很多

测试1:

//box2d


int main(int argc, char** argv)
{
	B2_NOT_USED(argc);
	B2_NOT_USED(argv);

	// Define the gravity vector.
	b2Vec2 gravity(0.0f, -9.8f);

	// Construct a world object, which will hold and simulate the rigid bodies.
	b2World world(gravity);

	// Define the ground body.
	//b2BodyDef groundBodyDef;
	//groundBodyDef.position.Set(0.0f, -10.0f);

	// Call the body factory which allocates memory for the ground body
	// from a pool and creates the ground box shape (also from a pool).
	// The body is also added to the world.
//	b2Body* groundBody = world.CreateBody(&groundBodyDef);

	// Define the ground box shape.
	//b2PolygonShape groundBox;

	// The extents are the half-widths of the box.
//	groundBox.SetAsBox(50.0f, 10.0f);

	// Add the ground fixture to the ground body.
	//groundBody->CreateFixture(&groundBox, 0.0f);

 
	// Set the box density to be non-zero, so it will be dynamic.
//	fixtureDef.density = 1.0f;

	// Override the default friction.
	//fixtureDef.friction = 0.3f;
	b2Body* body;// = world.CreateBody(&bodyDef);
	
	// Add the shape to the body.
//	body->CreateFixture(&fixtureDef);

	for (int i = 0; i < 100; i++)
	{
		// b2Body* body = world.CreateBody(&bodyDef);

		// Add the shape to the body.
	 	//body->CreateFixture(&fixtureDef);
	}
 
	for (int i = 0; i < 250; i++)
	{
		// Define the dynamic body. We set its position and call the body factory.
		b2BodyDef bodyDef;
		bodyDef.type = b2_dynamicBody;
		bodyDef.position.Set(0.0f, 0.0f);

		// Define another box shape for our dynamic body.
		b2PolygonShape dynamicBox;
		dynamicBox.SetAsBox(1.0f, 1.0f);

		// Define the dynamic body fixture.
		b2FixtureDef fixtureDef;
		fixtureDef.shape = &dynamicBox;


		bodyDef.type = b2_dynamicBody;
		 body = world.CreateBody(&bodyDef);
		 bodyDef.position.Set(1.0f, 1.0f*i);
 
		// Add the shape to the body.
		body->CreateFixture(&fixtureDef);
		//body->ApplyForceToCenter(b2Vec2(10.0f, 0.0f),true);
	}


	// Prepare for simulation. Typically we use a time step of 1/60 of a
	// second (60Hz) and 10 iterations. This provides a high quality simulation
	// in most game scenarios.
	float32 timeStep = 1.0f / 30.0f;
	int32 velocityIterations = 2;
	int32 positionIterations = 2;


/*	b2RayCastOutput output ;

	b2RayCastInput input;
	input.maxFraction = 12.0f;
	input.p1 = body->GetPosition();
	input.p2 = body->GetPosition();
	input.p2.x += 1.0f;*/
	int  t = time(nullptr);
	printf("start simulate\n");

	// This is our little game loop.
	for (int32 i = 0; i < 100; ++i)
	{
		// Instruct the world to perform a single step of simulation.
		// It is generally best to keep the time step and iterations fixed.
		world.Step(0.016f, 8, 2);

		// Now print the position and angle of the body.
	//	b2Vec2 position = body->GetPosition();
		//float32 angle = body->GetAngle();

		//printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle);
	}
	 
	cout << time(nullptr) - t <<"  "<< body->GetLinearVelocity().Length()<<"   "<< body->GetMass() <<"  "<< world.GetBodyCount() << endl;


	// When the world destructor is called, all bodies and joints are freed. This can
	// create orphaned pointers, so be careful about your world management.
	system("pause");
	return 0;
}
//physx


int main()
{
	PxDefaultAllocator gDefaultAllocatorCallback;




	static PxSampleAllocator* gAllocator = new PxSampleAllocator;





	//Recording memory allocations is necessary if you want to 
	//use the memory facilities in PVD effectively.  Since PVD isn't necessarily connected
	//right away, we add a mechanism that records all outstanding memory allocations and
	//forwards them to PVD when it does connect.

	//This certainly has a performance and memory profile effect and thus should be used
	//only in non-production builds.
	bool recordMemoryAllocations = true;
#ifdef RENDERER_ANDROID
	const bool useCustomTrackingAllocator = false;
#else
	const bool useCustomTrackingAllocator = true;
#endif

	PxAllocatorCallback* allocator = &gDefaultAllocatorCallback;


	auto mFoundation = PxCreateFoundation(PX_FOUNDATION_VERSION, *allocator, getSampleErrorCallback());



	PxTolerancesScale scale;

	auto mPvd = physx::PxCreatePvd(*mFoundation);

	auto mPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *mFoundation, scale, recordMemoryAllocations, mPvd);
	if (!mPhysics)
	{

	}
	if (!PxInitExtensions(*mPhysics, mPvd))
	{

	}
	PxCookingParams params(scale);
	params.meshWeldTolerance = 0.001f;
	params.meshPreprocessParams = PxMeshPreprocessingFlags(PxMeshPreprocessingFlag::eWELD_VERTICES);
	params.buildGPUData = true; //Enable GRB data being produced in cooking.

	// setup default material...
	auto 	mMaterial = mPhysics->createMaterial(0.5f, 0.5f, 0.1f);


	PxSceneDesc sceneDesc(mPhysics->getTolerancesScale());
	sceneDesc.filterShader = PxDefaultSimulationFilterShader;

	if (!sceneDesc.cpuDispatcher)
	{
		auto	mCpuDispatcher = PxDefaultCpuDispatcherCreate(0);

		sceneDesc.cpuDispatcher = mCpuDispatcher;
	}

	sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
	//	sceneDesc.flags |= PxSceneFlag::eENABLE_GPU_DYNAMICS;
	sceneDesc.flags |= PxSceneFlag::eENABLE_PCM;
	//sceneDesc.flags |= PxSceneFlag::eENABLE_AVERAGE_POINT;
	sceneDesc.flags |= PxSceneFlag::eENABLE_STABILIZATION;
	//sceneDesc.flags |= PxSceneFlag::eADAPTIVE_FORCE;
	sceneDesc.flags |= PxSceneFlag::eENABLE_ACTIVETRANSFORMS;
	sceneDesc.flags |= PxSceneFlag::eSUPPRESS_EAGER_SCENE_QUERY_REFIT;
	//sceneDesc.flags |= PxSceneFlag::eDISABLE_CONTACT_CACHE;
	//sceneDesc.broadPhaseType = PxBroadPhaseType::eGPU;
	sceneDesc.gpuMaxNumPartitions = 8;
	//	sceneDesc.flags |= PxSceneFlag::eREQUIRE_RW_LOCK;

	PxScene* scene = mPhysics->createScene(sceneDesc);
	PxRigidDynamic* box;
	for (int i = 0; i < 250; i++)
	{
		box = PxCreateDynamic(*mPhysics, PxTransform(PxVec3(0.0f, 0.0f, 0.0f)), PxBoxGeometry(PxVec3(1.0, 1.0 *i, 1.0)), *mMaterial, 0.5);
		box->setMass(0.0);
	//	box->setAngularDamping(100);

		scene->addActor(*box);

		box->addForce(PxVec3(10.0f, 0.0f, 0.0f));
	}
	auto tim = time(nullptr);

	for (int i = 0; i < 100; i++)
	{
		scene->simulate(0.016f);
		scene->fetchResults(true);
		//while (!scene->fetchResults(false))
		{

		}
	}
	cout << time(nullptr) - tim << "   " << box->getLinearVelocity().magnitude() << endl;

	//	scene->addActor(*box);

	system("pause");


	/*	gSampleCommandLine = new SampleCommandLine(GetCommandLineA());
		mainInitialize();
		mainLoop();
		mainTerminate();*/
	return 0;
}

调整为500个刚体  模拟10W次 输出结果为 

10个刚体 模拟100W次

2个刚体 模拟100W次

TODO

Scroll Up