//////// GAME-LEVEL RIGID BODY PHYSICS STUFF /////// void InitGamePhys() { #if WITH_BOX2D FPhysicsIntegration2D::InitializePhysics(); #endif #if WITH_PHYSX // Do nothing if SDK already exists if(GPhysXFoundation != NULL) { return; } // Make sure LoadPhysXModules(); // Create Foundation GPhysXAllocator = new FPhysXAllocator(); FPhysXErrorCallback* ErrorCallback = new FPhysXErrorCallback(); GPhysXFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, *GPhysXAllocator, *ErrorCallback); check(GPhysXFoundation); #if PHYSX_MEMORY_STATS // Want names of PhysX allocations GPhysXFoundation->setReportAllocationNames(true); #endif // Create profile manager GPhysXProfileZoneManager = &PxProfileZoneManager::createProfileZoneManager(GPhysXFoundation); check(GPhysXProfileZoneManager); // Create Physics PxTolerancesScale PScale; PScale.length = CVarToleranceScaleLength.GetValueOnGameThread(); PScale.mass = CVarTolerenceScaleMass.GetValueOnGameThread(); PScale.speed = CVarToleranceScaleSpeed.GetValueOnGameThread(); GPhysXSDK = PxCreatePhysics(PX_PHYSICS_VERSION, *GPhysXFoundation, PScale, false, GPhysXProfileZoneManager); check(GPhysXSDK); GPhysCommandHandler = new FPhysCommandHandler(); FCoreUObjectDelegates::PreGarbageCollect.AddRaw(GPhysCommandHandler, &FPhysCommandHandler::Flush); // Init Extensions PxInitExtensions(*GPhysXSDK); #if WITH_VEHICLE PxInitVehicleSDK(*GPhysXSDK); #endif //Turn on PhysX 3.3 unified height field collision detection. //This approach shares the collision detection code between meshes and height fields such that height fields behave identically to the equivalent terrain created as a mesh. //This approach facilitates mixing the use of height fields and meshes in the application with no tangible difference in collision behavior between the two approaches PxRegisterUnifiedHeightFields(*GPhysXSDK); #if WITH_PHYSICS_COOKING || WITH_RUNTIME_PHYSICS_COOKING // Create Cooking PxCookingParams PCookingParams(PScale); PCookingParams.meshWeldTolerance = 0.1f; // Weld to 1mm precision PCookingParams.meshPreprocessParams = PxMeshPreprocessingFlags(PxMeshPreprocessingFlag::eWELD_VERTICES | PxMeshPreprocessingFlag::eREMOVE_UNREFERENCED_VERTICES | PxMeshPreprocessingFlag::eREMOVE_DUPLICATED_TRIANGLES); PCookingParams.targetPlatform = PxPlatform::ePC; //PCookingParams.meshCookingHint = PxMeshCookingHint::eCOOKING_PERFORMANCE; //PCookingParams.meshSizePerformanceTradeOff = 0.0f; GPhysXCooking = PxCreateCooking(PX_PHYSICS_VERSION, *GPhysXFoundation, PCookingParams); check(GPhysXCooking); #endif #if WITH_APEX // Build the descriptor for the APEX SDK NxApexSDKDesc ApexDesc; ApexDesc.physXSDK = GPhysXSDK; // Pointer to the PhysXSDK ApexDesc.cooking = GPhysXCooking; // Pointer to the cooking library ApexDesc.renderResourceManager = &GApexNullRenderResourceManager; // We will not be using the APEX rendering API, so just use a dummy render resource manager ApexDesc.resourceCallback = &GApexResourceCallback; // The resource callback is how APEX asks the application to find assets when it needs them // Create the APEX SDK NxApexCreateError ErrorCode; GApexSDK = NxCreateApexSDK(ApexDesc, &ErrorCode); check(ErrorCode == APEX_CE_NO_ERROR); check(GApexSDK); #if APEX_STATICALLY_LINKED // We need to instantiate the module if we have statically linked them // Otherwise all createModule functions will fail instantiateModuleDestructible(); #if WITH_APEX_CLOTHING instantiateModuleClothing(); #endif #if WITH_APEX_LEGACY instantiateModuleLegacy(); #endif #endif // 1 legacy module for all in APEX 1.3 // Load the only 1 legacy module #if WITH_APEX_LEGACY GApexModuleLegacy = GApexSDK->createModule("Legacy"); check(GApexModuleLegacy); #endif // WITH_APEX_LEGACY // Load APEX Destruction module GApexModuleDestructible = static_cast<NxModuleDestructible*>(GApexSDK->createModule("Destructible")); check(GApexModuleDestructible); // Set Destructible module parameters NxParameterized::Interface* ModuleParams = GApexModuleDestructible->getDefaultModuleDesc(); // ModuleParams contains the default module descriptor, which may be modified here before calling the module init function GApexModuleDestructible->init(*ModuleParams); // Disabling dynamic LOD GApexModuleDestructible->setLODEnabled(false); // Set chunk report for fracture effect callbacks GApexModuleDestructible->setChunkReport(&GApexChunkReport); GApexModuleDestructible->setMaxDynamicChunkIslandCount((physx::PxU32)FMath::Max(CVarAPEXMaxDestructibleDynamicChunkIslandCount.GetValueOnGameThread(), 0)); GApexModuleDestructible->setMaxChunkCount((physx::PxU32)FMath::Max(CVarAPEXMaxDestructibleDynamicChunkCount.GetValueOnGameThread(), 0)); GApexModuleDestructible->setSortByBenefit(CVarAPEXSortDynamicChunksByBenefit.GetValueOnGameThread() != 0); GApexModuleDestructible->setChunkReportSendChunkStateEvents(true); // APEX 1.3 to preserve 1.2 behavior GApexModuleDestructible->setUseLegacyDamageRadiusSpread(true); GApexModuleDestructible->setUseLegacyChunkBoundsTesting(true); #if WITH_APEX_CLOTHING // Load APEX Clothing module GApexModuleClothing = static_cast<NxModuleClothing*>(GApexSDK->createModule("Clothing")); check(GApexModuleClothing); // Set Clothing module parameters ModuleParams = GApexModuleClothing->getDefaultModuleDesc(); // Can be tuned for switching between more memory and more spikes. NxParameterized::setParamU32(*ModuleParams, "maxUnusedPhysXResources", 5); // If true, let fetch results tasks run longer than the fetchResults call. // Setting to true could not ensure same finish timing with Physx simulation phase NxParameterized::setParamBool(*ModuleParams, "asyncFetchResults", false); // ModuleParams contains the default module descriptor, which may be modified here before calling the module init function GApexModuleClothing->init(*ModuleParams); #endif //WITH_APEX_CLOTHING #endif // #if WITH_APEX #endif // WITH_PHYSX }
//////// GAME-LEVEL RIGID BODY PHYSICS STUFF /////// void InitGamePhys() { #if WITH_BOX2D FPhysicsIntegration2D::InitializePhysics(); #endif #if WITH_PHYSX // Do nothing if SDK already exists if(GPhysXFoundation != NULL) { return; } // Make sure LoadPhysXModules(); // Create Foundation GPhysXAllocator = new FPhysXAllocator(); FPhysXErrorCallback* ErrorCallback = new FPhysXErrorCallback(); GPhysXFoundation = PxCreateFoundation(PX_FOUNDATION_VERSION, *GPhysXAllocator, *ErrorCallback); check(GPhysXFoundation); #if PHYSX_MEMORY_STATS // Want names of PhysX allocations GPhysXFoundation->setReportAllocationNames(true); #endif // Create profile manager GPhysXVisualDebugger = PxCreatePvd(*GPhysXFoundation); check(GPhysXVisualDebugger); // Create Physics PxTolerancesScale PScale; PScale.length = CVarToleranceScaleLength.GetValueOnGameThread(); PScale.speed = CVarToleranceScaleSpeed.GetValueOnGameThread(); GPhysXSDK = PxCreatePhysics(PX_PHYSICS_VERSION, *GPhysXFoundation, PScale, false, GPhysXVisualDebugger); check(GPhysXSDK); FPhysxSharedData::Initialize(); GPhysCommandHandler = new FPhysCommandHandler(); GPreGarbageCollectDelegateHandle = FCoreUObjectDelegates::PreGarbageCollect.AddRaw(GPhysCommandHandler, &FPhysCommandHandler::Flush); // Init Extensions PxInitExtensions(*GPhysXSDK, GPhysXVisualDebugger); #if WITH_VEHICLE PxInitVehicleSDK(*GPhysXSDK); #endif if (CVarUseUnifiedHeightfield.GetValueOnGameThread()) { //Turn on PhysX 3.3 unified height field collision detection. //This approach shares the collision detection code between meshes and height fields such that height fields behave identically to the equivalent terrain created as a mesh. //This approach facilitates mixing the use of height fields and meshes in the application with no tangible difference in collision behavior between the two approaches except that //heightfield thickness is not supported for unified heightfields. PxRegisterUnifiedHeightFields(*GPhysXSDK); } else { PxRegisterHeightFields(*GPhysXSDK); } if( FParse::Param( FCommandLine::Get(), TEXT( "PVD" ) ) ) { PvdConnect(TEXT("localhost"), true); } #if WITH_PHYSICS_COOKING || WITH_RUNTIME_PHYSICS_COOKING // Create Cooking PxCookingParams PCookingParams(PScale); PCookingParams.meshWeldTolerance = 0.1f; // Weld to 1mm precision PCookingParams.meshPreprocessParams = PxMeshPreprocessingFlags(PxMeshPreprocessingFlag::eWELD_VERTICES); // Force any cooking in PhysX or APEX to use older incremental hull method // This is because the new 'quick hull' method can generate degenerate geometry in some cases (very thin meshes etc.) //PCookingParams.convexMeshCookingType = PxConvexMeshCookingType::eINFLATION_INCREMENTAL_HULL; PCookingParams.targetPlatform = PxPlatform::ePC; //PCookingParams.meshCookingHint = PxMeshCookingHint::eCOOKING_PERFORMANCE; //PCookingParams.meshSizePerformanceTradeOff = 0.0f; GPhysXCooking = PxCreateCooking(PX_PHYSICS_VERSION, *GPhysXFoundation, PCookingParams); check(GPhysXCooking); #endif #if WITH_APEX // Build the descriptor for the APEX SDK apex::ApexSDKDesc ApexDesc; ApexDesc.foundation = GPhysXFoundation; // Pointer to the PxFoundation ApexDesc.physXSDK = GPhysXSDK; // Pointer to the PhysXSDK ApexDesc.cooking = GPhysXCooking; // Pointer to the cooking library ApexDesc.renderResourceManager = &GApexNullRenderResourceManager; // We will not be using the APEX rendering API, so just use a dummy render resource manager ApexDesc.resourceCallback = &GApexResourceCallback; // The resource callback is how APEX asks the application to find assets when it needs them #if PLATFORM_MAC FString DylibFolder = FPaths::EngineDir() / TEXT("Binaries/ThirdParty/PhysX/"); ANSICHAR* DLLLoadPath = (ANSICHAR*)FMemory::Malloc(DylibFolder.Len() + 1); FCStringAnsi::Strcpy(DLLLoadPath, DylibFolder.Len() + 1, TCHAR_TO_UTF8(*DylibFolder)); ApexDesc.dllLoadPath = DLLLoadPath; #endif // Create the APEX SDK apex::ApexCreateError ErrorCode; GApexSDK = apex::CreateApexSDK(ApexDesc, &ErrorCode); check(ErrorCode == APEX_CE_NO_ERROR); check(GApexSDK); #if PLATFORM_MAC FMemory::Free(DLLLoadPath); #endif #if UE_BUILD_SHIPPING GApexSDK->setEnableApexStats(false); #endif #if APEX_STATICALLY_LINKED // We need to instantiate the module if we have statically linked them // Otherwise all createModule functions will fail instantiateModuleDestructible(); #if WITH_APEX_CLOTHING instantiateModuleClothing(); #endif #if WITH_APEX_LEGACY instantiateModuleLegacy(); #endif #endif // 1 legacy module for all in APEX 1.3 // Load the only 1 legacy module #if WITH_APEX_LEGACY GApexModuleLegacy = GApexSDK->createModule("Legacy"); check(GApexModuleLegacy); #endif // WITH_APEX_LEGACY // Load APEX Destruction module GApexModuleDestructible = static_cast<apex::ModuleDestructible*>(GApexSDK->createModule("Destructible")); check(GApexModuleDestructible); // Set Destructible module parameters NvParameterized::Interface* ModuleParams = GApexModuleDestructible->getDefaultModuleDesc(); // ModuleParams contains the default module descriptor, which may be modified here before calling the module init function GApexModuleDestructible->init(*ModuleParams); // Set chunk report for fracture effect callbacks GApexModuleDestructible->setChunkReport(&GApexChunkReport); GApexModuleDestructible->setMaxDynamicChunkIslandCount((physx::PxU32)FMath::Max(CVarAPEXMaxDestructibleDynamicChunkIslandCount.GetValueOnGameThread(), 0)); GApexModuleDestructible->setMaxChunkCount((physx::PxU32)FMath::Max(CVarAPEXMaxDestructibleDynamicChunkCount.GetValueOnGameThread(), 0)); GApexModuleDestructible->setSortByBenefit(CVarAPEXSortDynamicChunksByBenefit.GetValueOnGameThread() != 0); GApexModuleDestructible->scheduleChunkStateEventCallback(apex::DestructibleCallbackSchedule::FetchResults); // APEX 1.3 to preserve 1.2 behavior GApexModuleDestructible->setUseLegacyDamageRadiusSpread(true); GApexModuleDestructible->setUseLegacyChunkBoundsTesting(true); #if WITH_APEX_CLOTHING // Load APEX Clothing module GApexModuleClothing = static_cast<apex::ModuleClothing*>(GApexSDK->createModule("Clothing")); check(GApexModuleClothing); // Set Clothing module parameters ModuleParams = GApexModuleClothing->getDefaultModuleDesc(); // Can be tuned for switching between more memory and more spikes. NvParameterized::setParamU32(*ModuleParams, "maxUnusedPhysXResources", 5); // If true, let fetch results tasks run longer than the fetchResults call. // Setting to true could not ensure same finish timing with Physx simulation phase NvParameterized::setParamBool(*ModuleParams, "asyncFetchResults", false); // ModuleParams contains the default module descriptor, which may be modified here before calling the module init function GApexModuleClothing->init(*ModuleParams); #endif //WITH_APEX_CLOTHING #endif // #if WITH_APEX #endif // WITH_PHYSX }