1

我仍在研究用于模拟流体的物理系统。我重写了我的应用程序以使用 PhysX 3.3.0 并且更加客观,现在我有一个问题,我无法在一两个星期内解决。

这是我对 PhysX Context 的启蒙:

void PhysXSPH::initContext(void){
    static LogPxErrorCallback gLogPxErrorCallback;
    static PxDefaultAllocator gDefaultAllocatorCallback;

    mFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gDefaultAllocatorCallback, gLogPxErrorCallback);
    check(mFoundation, "PxFoundation creating failed!");

    static PxProfileZoneManager *mProfileZoneManager = &PxProfileZoneManager::createProfileZoneManager(mFoundation);
    check(mProfileZoneManager, "PxProfileZoneManager creation failed!");

    bool recordMemoryAllocations = true;
    mPhysics = PxCreateBasePhysics(PX_PHYSICS_VERSION, *mFoundation,
        PxTolerancesScale(), recordMemoryAllocations, mProfileZoneManager );
    check(mPhysics, "PxPhysics creating failed!");

    PxRegisterParticles(*mPhysics);
    if(!PxInitExtensions(*mPhysics)){
        check(NULL, "PxInitExtensions failed!");
    }

    static PxSimulationFilterShader gDefaultFilterShader = PxDefaultSimulationFilterShader;
    PxSceneDesc sceneDesc(mPhysics->getTolerancesScale());

    sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);

    if(!sceneDesc.cpuDispatcher){
        mCpuDispatcher = PxDefaultCpuDispatcherCreate(4);
        check(mCpuDispatcher, "PxDefaultCpuDispatcherCreate failed!");
        sceneDesc.cpuDispatcher = mCpuDispatcher;
    }
    if(!sceneDesc.filterShader){
        sceneDesc.filterShader = gDefaultFilterShader;
    }

#ifdef PX_WINDOWS

    PxCudaContextManagerDesc cudaContextManagerDesc;
    mCudaContextManager = PxCreateCudaContextManager(*mFoundation, cudaContextManagerDesc, mProfileZoneManager);
    if( mCudaContextManager ){
        if( !mCudaContextManager->contextIsValid() ){
            mCudaContextManager->release();
            mCudaContextManager = NULL;
            CLOG(ERROR, "physX")<<"Invalid CUDA context.";
            exit(EXIT_FAILURE);
        }

        if(!sceneDesc.gpuDispatcher){
            sceneDesc.gpuDispatcher = mCudaContextManager->getGpuDispatcher();
        }
        CLOG(INFO, "physX")<<"CUDA context created.";
    } else {
        CLOG(ERROR, "physX")<<"Creating CUDA context manager failed.";
        exit(EXIT_FAILURE);
    }

#endif

    mScene = mPhysics->createScene(sceneDesc);
    check(mScene, "createScene failed!");

    createScene(mScene);
}

并启动 physX 场景,但即使是空场景也会出现问题:

void PhysXSPH::createScene(PxScene *mScene){
    mScene->setVisualizationParameter(PxVisualizationParameter::eSCALE, 1.0);
    mScene->setVisualizationParameter(PxVisualizationParameter::eCOLLISION_SHAPES, 1.0f);
    createPlanes(mScene);
    createParticles(mScene);
    CLOG(INFO, "physX") << "PhysX scene created.";
}

void PhysXSPH::createPlanes(PxScene *mScene){
    PxMaterial* mMaterial = mPhysics->createMaterial(0.5,0.5,0.5);

    //Create actors 
    //1) Create ground plane
    PxReal d = 0.0f;     
    PxTransform pose = PxTransform(PxVec3(0.0f, 0, 0.0f),PxQuat(PxHalfPi, PxVec3(0.0f, 0.0f, 1.0f)));

    PxRigidStatic* plane = mPhysics->createRigidStatic(pose);
    check(plane, "Creating plane failed!");

    //create 4 more planes for aquarium

    PxRigidStatic* plane2 = PxCreatePlane(*mPhysics, PxPlane(PxVec3(-4.0f, 0.0, 0.0), PxVec3(1.0, 0.0, 0.0)), *mMaterial);

    PxRigidStatic* plane3 = PxCreatePlane(*mPhysics, PxPlane(PxVec3(4.0f, 0.0, 0.0), PxVec3(-1.0, 0.0, 0.0)), *mMaterial);

    PxRigidStatic* plane4 = PxCreatePlane(*mPhysics, PxPlane(PxVec3(0.0f, 0.0, -4.0f), PxVec3(0.0, 0.0, 1.0)), *mMaterial);

    PxRigidStatic* plane5 = PxCreatePlane(*mPhysics, PxPlane(PxVec3(0.0f, 0.0, 4.0f), PxVec3(0.0, 0.0, -1.0)), *mMaterial);

    // create shape
    PxShape* shape = plane->createShape(PxPlaneGeometry(), *mMaterial);
    check(shape, "Creating shape failed!");

    mScene->addActor(*plane);

    PxShape* shape2 = plane2->createShape(PxPlaneGeometry(), *mMaterial);
    check(shape2, "Creating shape failed!");
    mScene->addActor(*plane2);


    PxShape* shape3 = plane3->createShape(PxPlaneGeometry(), *mMaterial);
    check(shape3, "Creating shape failed!");
    mScene->addActor(*plane3);

    PxShape* shape4 = plane4->createShape(PxPlaneGeometry(), *mMaterial);
    check(shape4, "Creating shape failed!");
    mScene->addActor(*plane4);

    PxShape* shape5 = plane5->createShape(PxPlaneGeometry(), *mMaterial);
    check(shape5, "Creating shape failed!");
    mScene->addActor(*plane5);
}

void PhysXSPH::createParticles(PxScene *mScene){
    // set immutable properties.
    bool perParticleRestOffset = false;

    //get data from scene model
    int maxParticles = scene->getMaxParticles();
    int xDim = scene->getXDim();
    int yDim = scene->getYDim();
    int zDim = scene->getZDim();

    // create particle system in PhysX SDK
    particleSystem = mPhysics->createParticleFluid(maxParticles, perParticleRestOffset);
    check(particleSystem, "Creating particle system failed!");

    particleSystem->setRestOffset(particleRadius);
    particleSystem->setRestParticleDistance(particleRadius);
    particleSystem->setParticleBaseFlag(PxParticleBaseFlag::eGPU,true);
    // TODO set fluid parameters


    // add particle system to scene, in case creation was successful
    if (particleSystem)
        mScene->addActor(*particleSystem);

    indexes = new PxU32[maxParticles];
    particle_positions = new PxVec3[maxParticles];

    int index=0;
    for(int x=0; x<xDim ;x++){
        for(int y=0; y<yDim ;y++){
            for(int z=0; z<zDim; z++){
                indexes[index]=(PxU32)index;
                int v=3*index;

                particle_positions[index]=PxVec3((physx::PxReal)(scene->m_vPos[v]), (physx::PxReal)(scene->m_vPos[v+1]), (physx::PxReal)(scene->m_vPos[v+2]));

                //CLOG(INFO, "physX")<<index<<"["<<particle_positions[index].x<<"; "<<particle_positions[index].y<<"; "<<particle_positions[index].z<<"]";
                index++;
            }
        }
    }

    PxParticleCreationData particleCreationData;
    particleCreationData.numParticles = maxParticles;
    particleCreationData.indexBuffer = PxStrideIterator<const PxU32>(indexes);
    particleCreationData.positionBuffer = PxStrideIterator<const PxVec3>(particle_positions);

    // create particles in *PxParticleSystem* ps
    bool success = particleSystem->createParticles(particleCreationData);
    if(!success){
        CLOG(ERROR, "physX")<<"Creating particles failed.";
        exit(EXIT_FAILURE);
    }
}

如果注释了#ifdef PX_WINDOWS 中的代码,则一切正常。流体按应有的方式流动。但是当我尝试使用我的 GPU 时,应用程序在第一次 fetchResult() 调用时冻结(simulate() 方法永远不会完成它的工作)。我没有错误日志,它只是冻结。无论是 DEBUG 还是 RELEASE,以及它是 32 还是 64 版本,都会发生这种情况。

我有一个 GeForce 560Ti。我使用 Physx SDK 3.3.0。我链接(例如在 win64 调试版本上)与:

opengl32.lib glew32.lib glfw3.lib PhysX3DEBUG_x64.lib PhysX3CommonDEBUG_x64.lib PxTaskDEBUG.lib PhysX3ExtensionsDEBUG.lib PhysXProfileSDKDEBUG.lib

使用:

nvToolsExt64_1.dll PhysX3XHECKED_x64.dll PhysX3CommonCHECKED_x64.dll PhysX3GpuCHECKED_x64.dll PhysX3GpuDEBUG_x64.dll

我尝试使用不同版本的 .libs 并添加应用程序所需的 .dlls,但每组最终都会在 fetchResult() 上冻结。

我不知道在哪里寻找错误。一切看起来都很好。我会很感激任何帮助!

4

1 回答 1

1

我知道这是一个旧线程,但是当我从 3.2.5 切换到 3.3.0 时,我遇到了完全相同的问题。

我确实找到了解决方案。问题是你在这里初始化了两次扩展。您正在使用PxCreateBasePhysics创建您的 SDK 对象,该对象在后台执行一些额外的工作。也就是说,PxInitExtensions如果我没记错的话,它会调用。

解决方法是将函数更改为具有完全相同参数PxCreateBasePhysics的标准调用。PxCreatePhysics这个在幕后没有做任何额外的设置。只是不接InitExtensions电话也可以,但我只尝试了第一个想法。

奇怪的是,这只会在使用 GPU 时导致冻结,也许 nVidia 应该看看它。

于 2014-08-28T21:30:07.807 回答