Hi.
I think the physx lib is MT, But on a lot of other forums, there all saying that the physx is MD, how come now its MT.
I can't find any vc solution to compile the libs to MD The only files in the SDK PhysX is PhysXExtensions.sln(I built this one), PhysXVehicle.sln, but the Physx PhysX3_x86.lib build solution is nowhere to be seen.
Does this statement hold true MT will pack the lib within the exe. if thats true the physx doc says we need to ship there dll with the app ???.
I can't use MT its fine for my test app but the rest of the apps I would like to add physx to use MD, boost, google protocol buffers.
A dumb Question??? if I compile the project with MT when the app closes the memory leak pops up.
I am using this here to detect memory leaks.
.
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
Does the above not work with MT(I think MT holds its own copy of the lib).
heres the app in its current form using MD setup.
But Im doing the class wrong because I need to #progma in the . Hpp file I think its tricking the compiler to work.???
.
#ifndef PHYSX_H
#define PHYSX_H
#include <iostream>
#include <pxphysicsapi.h>
#include <extensions//pxdefaulterrorcallback.h>
#include <extensions//pxdefaultallocator.h>
//#include <string>
//to use this class you will need to include the following libs
//and also copy to the apps root folder
//nvToolsExt32_1.dll
//PhysX3_x86.dll
//PhysX3Common_x86.dll
//PhysX3CommonDEBUG_x86.dll
//PhysX3DEBUG_x86.dll
//don't include the debug dll's in release
//THIS BIT HERE IS BAD ???????????????????
//also you need to link the following libs in vc
#if defined(DEBUG) || defined(_DEBUG)
#pragma comment(lib, "PhysX3DEBUG_x86.lib")
#pragma comment(lib, "PhysXProfileSDKDEBUG.lib")
#pragma comment(lib, "PhysX3ExtensionsDEBUG.lib")
#pragma comment(lib, "PhysX3CommonDEBUG_x86.lib")
#else
#pragma comment(lib, "PhysX3_x86.lib")
#pragma comment(lib, "PhysXProfileSDK.lib")
#pragma comment(lib, "PhysX3Extensions.lib")
#pragma comment(lib, "PhysX3Common_x86.lib")
#endif
//------------------------------------------------------------------------------
//this class will initialize the physX objects and scene and
//you will need to call releasePhysX
//------------------------------------------------------------------------------
class cPhysX
{
public:
cPhysX();
~cPhysX();
void ShutdownPhysX();
//----------------------------------------------------------------------
//if the debug flag is true we create the profilemanager
//----------------------------------------------------------------------
bool InitializePhysX(bool ddg);
//public members
physx::PxFoundation *gFoundation;
physx::PxPhysics *gPhysicsSDK;
physx::PxDefaultCpuDispatcher* gDispatcher;
physx::PxScene *gScene;
physx::PxDefaultErrorCallback gDefaultErrorCallback;
physx::PxDefaultAllocator gDefaultAllocatorCallback;
physx::PxProfileZoneManager* gProfileZoneManager;
//error message
std::string ErrorMsg;
};//end class cPhysX
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#endif
Cpp file
.
cPhysX::cPhysX()
{
gFoundation = NULL;
gPhysicsSDK = NULL;
gDispatcher = NULL;
gScene = NULL;
gProfileZoneManager = NULL;
}//end con
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
cPhysX::~cPhysX()
{
}//end destructor
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
void cPhysX::ShutdownPhysX()
{
if(gScene)
gScene->release();
if(gDispatcher)
gDispatcher->release();
if(gPhysicsSDK)
gPhysicsSDK->release();
if(gProfileZoneManager)
gProfileZoneManager->release();
if(gFoundation)
gFoundation->release();
gFoundation = NULL;
gPhysicsSDK = NULL;
gDispatcher = NULL;
gScene = NULL;
gProfileZoneManager = NULL;
}//end ShutdownPhysX
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------
//if the debug flag is true we create the profilemanager
//----------------------------------------------------------------------
bool cPhysX::InitializePhysX(bool ddg)
{
if(gFoundation)
return true;
ErrorMsg = "No Errors";
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gDefaultAllocatorCallback, gDefaultErrorCallback);
if(gFoundation == NULL)
{
ErrorMsg = "Error creating gFoundation.";
return false;
}
if(ddg)
{
gProfileZoneManager = &physx::PxProfileZoneManager::createProfileZoneManager(gFoundation);
if(gProfileZoneManager == NULL)
{
ErrorMsg = "Error creating gProfileZoneManager.";
return false;
}
}
bool recordMemoryAllocations = ddg;
gPhysicsSDK = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, physx::PxTolerancesScale(), recordMemoryAllocations, gProfileZoneManager);
if(gPhysicsSDK == NULL)
{
ErrorMsg = "Error creating PhysX device.";
return false;
}
return true;//all ok
}//end InitializePhysX
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Main.Cpp
.
#include <iostream>
#include <vector>
#include<physx.h>
/*
#if defined(DEBUG) || defined(_DEBUG)
#pragma comment(lib, "PhysX3DEBUG_x86.lib")
#pragma comment(lib, "PhysXProfileSDKDEBUG.lib")
#pragma comment(lib, "PhysX3ExtensionsDEBUG.lib")
#pragma comment(lib, "PhysX3CommonDEBUG_x86.lib")
#else
#pragma comment(lib, "PhysX3_x86.lib")
#pragma comment(lib, "PhysXProfileSDK.lib")
#pragma comment(lib, "PhysX3Extensions.lib")
#pragma comment(lib, "PhysX3Common_x86.lib")
#endif
*/
//#include <pxphysicsapi.h>
//#include <extensions//pxdefaulterrorcallback.h>
//#include <extensions//pxdefaultallocator.h>
//The PhysX header is now PxPhysicsAPI.h. This header is needed for PhysX. The rest are for c++ output/input stuff and
//freeglut API stuff. I like to programmatically add the linker libraries.
//For this basic startup demo, we need PhysX3_x86.lib/dll, Foundation.lib/dll, PhysX3Extensions.lib/dll so we link to them.
//const int WINDOW_WIDTH=1024, WINDOW_HEIGHT=768;
//physx::PxFoundation *gFoundation = nullptr;
//physx::PxPhysics *gPhysicsSDK = nullptr;
//physx::PxDefaultCpuDispatcher* gDispatcher = NULL;
//physx::PxScene *gScene = nullptr;
//physx::PxDefaultErrorCallback gDefaultErrorCallback;
//physx::PxDefaultAllocator gDefaultAllocatorCallback;
//physx::PxProfileZoneManager* gProfileZoneManager = nullptr;
//IN the above lines, we setup the window dimensions. Then we store the PhysX object pointer. In the previous sdk,
//only first parameter was needed now all of the parameters are needed. These include the allocator and error callback handlers.
//The sdk provides default handlers so we use them.
//Thats it. The code should not give u any errors. To make sure everything is fine and there are no problems,
//copy PhysX3_x86.dll to the current solution directory. Hope you will enjoy the rest of the tutorials.
/*
void InitializePhysX()
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gDefaultAllocatorCallback, gDefaultErrorCallback);
if(gFoundation == nullptr)
{
std::cerr<<"Error creating gFoundation."<<std::endl;
std::getchar();
std::cerr<<"Exiting..."<<std::endl; exit(1);
}
gProfileZoneManager = &physx::PxProfileZoneManager::createProfileZoneManager(gFoundation);
if(gProfileZoneManager == nullptr)
{
std::cerr<<"Error creating gProfileZoneManager."<<std::endl;
std::getchar();
std::cerr<<"Exiting..."<<std::endl; exit(1);
}
bool recordMemoryAllocations = true;
gPhysicsSDK = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, physx::PxTolerancesScale(), recordMemoryAllocations, gProfileZoneManager);
if(gPhysicsSDK == nullptr)
{
std::cerr<<"Error creating PhysX device."<<std::endl;
std::getchar();
std::cerr<<"Exiting..."<<std::endl; exit(1);
}
}
void ShutdownPhysX()
{
gScene->release();
gDispatcher->release();
gPhysicsSDK->release();
gProfileZoneManager->release();
gFoundation->release();
}
*/
//How do I convert a quaternion to a rotation axis and angle?
//----------------------------------------------------------------
// A quaternion can be converted back to a rotation axis and angle
//using the following algorithm:
//---------------------------------------------------
void QuaternionToAxisAngle(physx::PxVec3 &axis, physx::PxQuat &qr1)
{
physx::PxQuat qr = qr1;
qr.normalize();
double PI = 3.14159265;
double RADIANS = (180 / PI); //
double cos_angle = qr.w;
double angle = acos( cos_angle ) * 2 * RADIANS;
double sin_angle = sqrt( 1.0 - cos_angle * cos_angle );
double sa = sin_angle;
if ( fabs( sin_angle ) < 0.0005 )
sa = 1;
axis.x = qr.x / sa;
axis.y = qr.y / sa;
axis.z = qr.z / sa;
}
physx::PxFilterFlags contactReportFilterShader(physx::PxFilterObjectAttributes attributes0, physx::PxFilterData filterData0,
physx::PxFilterObjectAttributes attributes1, physx::PxFilterData filterData1,
physx::PxPairFlags& pairFlags, const void* constantBlock, physx::PxU32 constantBlockSize)
{
PX_UNUSED(attributes0);
PX_UNUSED(attributes1);
PX_UNUSED(filterData0);
PX_UNUSED(filterData1);
PX_UNUSED(constantBlockSize);
PX_UNUSED(constantBlock);
// all initial and persisting reports for everything, with per-point data
pairFlags = physx::PxPairFlag::eRESOLVE_CONTACTS
| physx::PxPairFlag::eNOTIFY_TOUCH_FOUND
| physx::PxPairFlag::eNOTIFY_TOUCH_PERSISTS
| physx::PxPairFlag::eNOTIFY_CONTACT_POINTS;
return physx::PxFilterFlag::eDEFAULT;
}
class ContactReportCallback: public physx::PxSimulationEventCallback
{
void onConstraintBreak(physx::PxConstraintInfo* constraints, physx::PxU32 count) { PX_UNUSED(constraints); PX_UNUSED(count); }
void onWake(physx::PxActor** actors, physx::PxU32 count) { PX_UNUSED(actors); PX_UNUSED(count); }
void onSleep(physx::PxActor** actors, physx::PxU32 count) { PX_UNUSED(actors); PX_UNUSED(count); }
void onTrigger(physx::PxTriggerPair* pairs, physx::PxU32 count) { PX_UNUSED(pairs); PX_UNUSED(count); }
void onContact(const physx::PxContactPairHeader& pairHeader, const physx::PxContactPair* pairs, physx::PxU32 nbPairs)
{
PX_UNUSED((pairHeader));
std::vector<physx::PxContactPairPoint> contactPoints;
for(physx::PxU32 i=0;i<nbPairs;i++)
{
physx::PxU32 contactCount = pairs[i].contactCount;
if(contactCount)
{
contactPoints.resize(contactCount);
pairs[i].extractContacts(&contactPoints[0], contactCount);
for(physx::PxU32 j=0;j<contactCount;j++)
{
//lost shapes we dont want
if( pairs[i].events & physx::PxPairFlag::eNOTIFY_TOUCH_FOUND)
{
if(pairs[i].shapes[0]->getActor()->userData)
{
int *ballid = reinterpret_cast<int*>(pairs[i].shapes[0]->getActor()->userData);
std::cout << "**********************OnCollision Ball ID = " << *ballid << " Shape Number = 0" <<std::endl;
std::getchar();
}
if(pairs[i].shapes[1]->getActor()->userData)
{
int *ballid = reinterpret_cast<int*>(pairs[i].shapes[1]->getActor()->userData);
std::cout << "**********************OnCollision Ball ID = " << *ballid << " Shape Number = 1" <<std::endl;
std::getchar();
}
}
//gContactPositions.push_back(contactPoints[j].position);
//gContactImpulses.push_back(contactPoints[j].impulse);
}
}
}
}
};
ContactReportCallback gContactReportCallback;
int main(int argc, char* argv[])
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
//InitializePhysX();
cPhysX PhysX;
int BallID = 3;
//we want to check memorey true debug only
if(PhysX.InitializePhysX(true) == false)
{
std::cout << "Error creating PhysX device." << PhysX.ErrorMsg.c_str() << std::endl;
std::getchar();
std::cerr<<"Exiting..."<<std::endl; exit(1);
}
//we create the scene out side
physx::PxSceneDesc sceneDesc(PhysX.gPhysicsSDK->getTolerancesScale());
sceneDesc.gravity = physx::PxVec3(0.0f, -9.81f, 0.0f);
PhysX.gDispatcher = physx::PxDefaultCpuDispatcherCreate(1);
sceneDesc.cpuDispatcher =PhysX.gDispatcher;
sceneDesc.filterShader = contactReportFilterShader;//physx::PxDefaultSimulationFilterShader;
sceneDesc.simulationEventCallback = &gContactReportCallback;
PhysX.gScene = PhysX.gPhysicsSDK->createScene(sceneDesc);
//we want a ball we will drop it down
physx::PxSphereGeometry gSphereGeometry(20);
physx::PxTransform t(physx::PxVec3(0,100,0));
physx::PxMaterial *gMaterialSphere = NULL;
physx::PxMaterial *gMaterialPlane = NULL;
gMaterialSphere = PhysX.gPhysicsSDK->createMaterial(0.01f, 0.01f, 1.0f);
gMaterialPlane = PhysX.gPhysicsSDK->createMaterial(0.5f, 0.5f, 0.0f);
physx::PxVec3 velocity = physx::PxVec3(0,-60,0);
physx::PxRigidDynamic* dynamic = physx::PxCreateDynamic(*PhysX.gPhysicsSDK, t, gSphereGeometry, *gMaterialSphere, 1000.0f);
dynamic->setAngularDamping(0.0f);
dynamic->setLinearVelocity(velocity);
dynamic->userData = (void*)&BallID;
PhysX.gScene->addActor(*dynamic);
//ground plane
physx::PxRigidStatic* groundPlane = physx::PxCreatePlane(*PhysX.gPhysicsSDK, physx::PxPlane(0,1,0,0), *gMaterialPlane);
PhysX.gScene->addActor(*groundPlane);
physx::PxShape* shapes[10];
std::vector<physx::PxRigidActor*> actors;
//test update
for(int ctr = 0; ctr < 600; ++ctr)
{
PhysX.gScene->simulate(0.01666);//1.0f/60.0f);
PhysX.gScene->fetchResults(true);
//print the balls position | physx::PxActorTypeSelectionFlag::eRIGID_STATIC
physx::PxU32 nbActors = PhysX.gScene->getNbActors(physx::PxActorTypeSelectionFlag::eRIGID_DYNAMIC );
if(nbActors)
{
actors.resize(nbActors);// | physx::PxActorTypeSelectionFlag::eRIGID_STATIC
PhysX.gScene->getActors(physx::PxActorTypeSelectionFlag::eRIGID_DYNAMIC, (physx::PxActor**)&actors[0], nbActors);
for(physx::PxU32 i=0;i<actors.size();i++)
{
const physx::PxU32 nbShapes = actors[i]->getNbShapes();
actors[i]->getShapes(shapes, nbShapes);
bool sleeping = actors[i]->isRigidDynamic() ? actors[i]->isRigidDynamic()->isSleeping() : false;
for(physx::PxU32 j=0;j<nbShapes;j++)
{
const physx::PxMat44 shapePose(physx::PxShapeExt::getGlobalPose(*shapes[j], *actors[i]));
//PxGeometryHolder h = shapes[j]->getGeometry();
//if (shapes[j]->getFlags() & physx::PxShapeFlag::eTRIGGER_SHAPE)
physx::PxVec3 pos = shapePose.getPosition();
std::cout << "sphere height: " << pos.y << " X = " << pos.x << " Z = " << pos.z << std::endl;
//physx::PxTransform Pose = actors[i]->getGlobalPose();
//pos = Pose.p;
//QuaternionToAxisAngle(pos, Pose.q);
//std::cout << "Angle Axis sphere X: " << pos.x << " Y = " << pos.y << " Z = " << pos.z << std::endl;
}//end all shapes
}//end all actors
}//end nbactor
}
std::getchar();
PhysX.ShutdownPhysX();
return 0;
}
Notice if the code is in the main.cpp it compiles fine and runs.
I'm lost.
Oh I just found this.
Note:
The static libraries we provide with the Windows binary distribution are linked against the Multi-Threaded static C Run-Time (CRT) libraries. This means that your application must also use the same CRT flavor. If you need to use a different CRT version, you must upgrade to our source license. The source distribution can simply be recompiled using different CRT settings.