bool DelayedInitializer::eventFilter( QObject *receiver, QEvent *event )
{
    if ( m_signalEmitted || event->type() != m_eventType )
        return false;

    m_signalEmitted = true;
    receiver->removeEventFilter( this );

    // Move the emitting of the event to the end of the eventQueue
    // so we are absolutely sure the event we get here is handled before
    // the initialize is fired.
    QTimer::singleShot( 0, this, SLOT( slotInitialize() ) );

    return false;
}
示例#2
0
void ParticleSystem::slotResetParticles()
{
    qDebug() << __PRETTY_FUNCTION__;

    if(!mIsInitialized) slotInitialize();

    // When re-setting particles, also reset their position of last collision!
    cudaSafeCall(cudaMemset(mDeviceParticleCollisionPositions, 0, mParametersSimulation->particleCount * 4 * sizeof(float)));

    switch(mDefaultParticlePlacement)
    {
    case ParticlePlacement::PlacementRandom:
    {
        int p = 0, v = 0;

        qDebug() << __PRETTY_FUNCTION__ << "world min" << mParametersSimulation->gridParticleSystem.worldMin.x << mParametersSimulation->gridParticleSystem.worldMin.y << mParametersSimulation->gridParticleSystem.worldMin.z <<
                    "max" << mParametersSimulation->gridParticleSystem.worldMax.x << mParametersSimulation->gridParticleSystem.worldMax.y << mParametersSimulation->gridParticleSystem.worldMax.z;

        for(unsigned int i=0; i < mParametersSimulation->particleCount; i++)
        {
            mHostParticlePos[p++] = mParametersSimulation->gridParticleSystem.worldMin.x + (mParametersSimulation->gridParticleSystem.worldMax.x - mParametersSimulation->gridParticleSystem.worldMin.x) * frand();
            mHostParticlePos[p++] = mParametersSimulation->gridParticleSystem.worldMin.y + (mParametersSimulation->gridParticleSystem.worldMax.y - mParametersSimulation->gridParticleSystem.worldMin.y) * frand();
            mHostParticlePos[p++] = mParametersSimulation->gridParticleSystem.worldMin.z + (mParametersSimulation->gridParticleSystem.worldMax.z - mParametersSimulation->gridParticleSystem.worldMin.z) * frand();
            mHostParticlePos[p++] = 1.0f;

            mHostParticleVel[v++] = 0.0f;
            mHostParticleVel[v++] = 0.0f;
            mHostParticleVel[v++] = 0.0f;
            mHostParticleVel[v++] = 0.0f;
        }
        break;
    }

    case ParticlePlacement::PlacementGrid:
    {
        const float jitter = mParametersSimulation->particleRadius * 0.01f;
        const float spacing = mParametersSimulation->particleRadius * 2.0f;

        // If we want a cube, determine the number of particles in each dimension
        unsigned int s = (int) ceilf(powf((float) mParametersSimulation->particleCount, 1.0f / 3.0f));
        unsigned int gridSize[3];
        gridSize[0] = gridSize[1] = gridSize[2] = s;

        srand(1973);
        for(unsigned int z=0; z<gridSize[2]; z++)
        {
            for(unsigned int y=0; y<gridSize[1]; y++)
            {
                for(unsigned int x=0; x<gridSize[0]; x++)
                {
                    unsigned int i = (z*gridSize[1]*gridSize[0]) + (y*gridSize[0]) + x;
                    if (i < mParametersSimulation->particleCount)
                    {
                        mHostParticlePos[i*4+0] = (spacing * x) + mParametersSimulation->particleRadius - 1.0f + (frand()*2.0f-1.0f)*jitter;
                        mHostParticlePos[i*4+1] = (spacing * y) + mParametersSimulation->particleRadius - 1.0f + (frand()*2.0f-1.0f)*jitter;
                        mHostParticlePos[i*4+2] = (spacing * z) + mParametersSimulation->particleRadius - 1.0f + (frand()*2.0f-1.0f)*jitter;
                        mHostParticlePos[i*4+3] = 1.0f;

                        mHostParticleVel[i*4+0] = 0.0f;
                        mHostParticleVel[i*4+1] = 0.0f;
                        mHostParticleVel[i*4+2] = 0.0f;
                        mHostParticleVel[i*4+3] = 0.0f;
                    }
                }
            }
        }
        break;
    }

    case ParticlePlacement::PlacementFillSky:
    {
        float jitter = mParametersSimulation->particleRadius * 0.1f;
        const float spacing = mParametersSimulation->particleRadius * 2.02f;

        unsigned int particleNumber = 0;

        for(
            float y = mParametersSimulation->gridParticleSystem.worldMax.y - mParametersSimulation->particleRadius;
            y >= mParametersSimulation->gridParticleSystem.worldMin.y + mParametersSimulation->particleRadius && particleNumber < mParametersSimulation->particleCount;
            y -= spacing)
        {

            for(
                float x = mParametersSimulation->gridParticleSystem.worldMin.x + mParametersSimulation->particleRadius;
                x <= mParametersSimulation->gridParticleSystem.worldMax.x - mParametersSimulation->particleRadius && particleNumber < mParametersSimulation->particleCount;
                x += spacing)
            {
                for(
                    float z = mParametersSimulation->gridParticleSystem.worldMin.z + mParametersSimulation->particleRadius;
                    z <= mParametersSimulation->gridParticleSystem.worldMax.z - mParametersSimulation->particleRadius && particleNumber < mParametersSimulation->particleCount;
                    z += spacing)
                {
                    //                    qDebug() << "moving particle" << particleNumber << "to" << x << y << z;
                    mHostParticlePos[particleNumber*4+0] = x + (frand()-0.5) * jitter;
                    mHostParticlePos[particleNumber*4+1] = y + (frand()-0.5) * jitter;
                    mHostParticlePos[particleNumber*4+2] = z + (frand()-0.5) * jitter;
                    mHostParticlePos[particleNumber*4+3] = 1.0f;

                    mHostParticleVel[particleNumber*4+0] = 0.0f;
                    mHostParticleVel[particleNumber*4+1] = 0.0f;
                    mHostParticleVel[particleNumber*4+2] = 0.0f;
                    mHostParticleVel[particleNumber*4+3] = 0.0f;

                    particleNumber++;
                }
            }
        }
        break;
    }
    }

    setArray(ArrayPositions, mHostParticlePos, 0, mParametersSimulation->particleCount);
    setArray(ArrayVelocities, mHostParticleVel, 0, mParametersSimulation->particleCount);
}
示例#3
0
// step the simulation
void ParticleSystem::update(quint8 *deviceGridMapOfWayPointPressure)
{
    //qDebug() << __PRETTY_FUNCTION__;

    //if(mParametersSimulation->gridParticleSystem.worldMax.x == 0.0f) return; // why this?

    if(!mIsInitialized) slotInitialize();

    QTime startTime = QTime::currentTime();
    startTime.start();

    // Get a pointer to the particle positions in the device by mapping GPU mem into CPU mem
    float *deviceParticlePositions = (float*)CudaHelper::mapGLBufferObject(&mCudaVboResourceParticlePositions);

    //qDebug() << __PRETTY_FUNCTION__ << "0: getting pointer finished at" << startTime.elapsed();

    // Update constants
    copyParametersToGpu(mParametersSimulation);

    //qDebug() << __PRETTY_FUNCTION__ << "1: setting parameters finished at" << startTime.elapsed();

    // Get a pointer to the "__constant__ ParametersParticleSystem parametersParticleSystem" on the device
    ParametersParticleSystem* paramsParticleSystem;
    getDeviceAddressOfParametersParticleSystem(&paramsParticleSystem);

    // Integrate
    integrateSystem(
                deviceParticlePositions,                    // in/out: The particle positions, unsorted
                mDeviceParticleVel,                         // in/out: The particle velocities, unsorted
                deviceGridMapOfWayPointPressure,            // output: A grid mapping the 3d-space to waypoint pressure. Cells with high values (255) should be visited for information gain.
                mDeviceParticleCollisionPositions,          // input:  The particle's last collision position (or 0 if it didn't collide yet)
                paramsParticleSystem,                       // input:  The particle system's parameters
                mParametersSimulation->particleCount);

    //    showInformationGain();

    //qDebug() << __PRETTY_FUNCTION__ << "2: integrating system finished at" << startTime.elapsed();

    // Now that particles have been moved, they might be contained in different grid cells. So recompute the
    // mapping gridCell => particleIndex. This will allow fast neighbor searching in the grid during collision phase.
    computeMappingFromPointToGridCell(
                mDeviceParticleMapGridCell,                 // output: The key - part of the particle gridcell->index map, unsorted
                mDeviceParticleMapIndex,                    // output: The value-part of the particle gridcell->index map, unsorted
                deviceParticlePositions,                    // input:  The particle positions after integration, unsorted and possibly colliding with other particles
                &paramsParticleSystem->gridParticleSystem,
                mParametersSimulation->particleCount);       // input:  The number of particles, one thread per particle

    //qDebug() << __PRETTY_FUNCTION__ << "3: computing particle spatial hash table finished at" << startTime.elapsed();

    // Sort the mapping gridCell => particleId on gridCell
    sortGridOccupancyMap(mDeviceParticleMapGridCell, mDeviceParticleMapIndex, mParametersSimulation->particleCount);

    //qDebug() << __PRETTY_FUNCTION__ << "4: sorting particle spatial hash table finished at" << startTime.elapsed();

    // Reorder particle arrays into sorted order and find start and end of each cell. The ordering of the particles is useful
    // only for the particle/particle-collisions. The collision code writes the post-collision velocities back into the
    // original, unsorted particle velocity array, where is will be used again in the next iteration's integrateSystem().
    sortParticlePosAndVelAccordingToGridCellAndFillCellStartAndEndArrays(
                mDeviceParticleCellStart,                           // output: At which index in mDeviceMapParticleIndex does cell X start?
                mDeviceParticleCellEnd,                             // output: At which index in mDeviceMapParticleIndex does cell X end?
                mDeviceParticleSortedPos,                   // output: The particle positions, sorted by gridcell
                mDeviceParticleSortedVel,                   // output: The particle velocities, sorted by gridcell
                mDeviceParticleMapGridCell,                 // input:  The key - part of the particle gridcell->index map, unsorted
                mDeviceParticleMapIndex,                    // input:  The value-part of the particle gridcell->index map, unsorted
                deviceParticlePositions,                    // input:  The particle-positions, unsorted
                mDeviceParticleVel,                         // input:  The particle-velocities, unsorted
                mParametersSimulation->particleCount,        // input:  The number of particles
                mParametersSimulation->gridParticleSystem.getCellCount()  // input: Number of grid cells
                );

    //qDebug() << __PRETTY_FUNCTION__ << "5: computing particle navigation tables and sorting particles finished at" << startTime.elapsed();

    // Same for colliders
    if(mUpdateMappingFromColliderToGridCell)
    {
        float *deviceColliderPositions = (float*)CudaHelper::mapGLBufferObject(&mCudaVboResourceColliderPositions);

        computeMappingFromPointToGridCell(
                    mDeviceColliderMapGridCell,                 // output: The key - part of the collider gridcell->index map, unsorted
                    mDeviceColliderMapIndex,                    // output: The value-part of the collider gridcell->index map, unsorted
                    deviceColliderPositions,                    // input:  The collider positions (no integration), unsorted and possibly colliding with particles
                    &paramsParticleSystem->gridParticleSystem,
                    mPointCloudColliders->getRenderInfo()->at(0)->size  // input:  The number of colliders, one thread per particle
                );

        //qDebug() << __PRETTY_FUNCTION__ << "6: computing collider spatial hash table finished at" << startTime.elapsed();

        sortGridOccupancyMap(mDeviceColliderMapGridCell, mDeviceColliderMapIndex, mPointCloudColliders->getRenderInfo()->at(0)->size);

        //qDebug() << __PRETTY_FUNCTION__ << "7: sorting collider spatial hash table finished at" << startTime.elapsed();

        sortParticlePosAndVelAccordingToGridCellAndFillCellStartAndEndArrays(
                    mDeviceColliderCellStart,                   // output: At which index in mDeviceMapColliderIndex does cell X start?
                    mDeviceColliderCellEnd,                     // output: At which index in mDeviceMapColliderIndex does cell X end?
                    mDeviceColliderSortedPos,                   // output: The collider positions, sorted by gridcell
                    0,                                          // output: The collider velocities, sorted by gridcell / they have no vel, so pass 0
                    mDeviceColliderMapGridCell,                 // input:  The key - part of the collider gridcell->index map, unsorted
                    mDeviceColliderMapIndex,                    // input:  The value-part of the collider gridcell->index map, unsorted
                    deviceColliderPositions,                    // input:  The particle-positions, unsorted
                    0,                                          // input:  The particle-velocities, unsorted / they have no vel, so pass 0
                    mPointCloudColliders->getRenderInfo()->at(0)->size, // input:  The number of colliders
                mParametersSimulation->gridParticleSystem.cells.x * mParametersSimulation->gridParticleSystem.cells.y * mParametersSimulation->gridParticleSystem.cells.z  // input: Number of grid cells
                );

        cudaGraphicsUnmapResources(1, &mCudaVboResourceColliderPositions, 0);

        mUpdateMappingFromColliderToGridCell = false;
    }

    //qDebug() << __PRETTY_FUNCTION__ << "8: computing collider navigation tables and sorting particles finished at" << startTime.elapsed();

    // process collisions between particles
    collideParticlesWithParticlesAndColliders(
                mDeviceParticleVel,                         // output: The particle velocities
                deviceParticlePositions,                    // output: The w-component is changed whenever a particle has hit a collider. Used just for visualization.
                mDeviceParticleCollisionPositions,          // output: Every particle's position of last collision, or 0.0/0.0/0.0 if none occurred.

                mDeviceParticleSortedPos,                   // input:  The particle positions, sorted by gridcell
                mDeviceParticleSortedVel,                   // input:  The particle velocities, sorted by gridcell
                mDeviceParticleMapIndex,                    // input:  The value-part of the particle gridcell->index map, sorted by gridcell
                mDeviceParticleCellStart,                   // input:  At which index in mDeviceMapParticleIndex does cell X start?
                mDeviceParticleCellEnd,                     // input:  At which index in mDeviceMapParticleIndex does cell X end?

                mDeviceColliderSortedPos,                   // input:  The collider positions, sorted by gridcell
                mDeviceColliderMapIndex,                    // input:  The value-part of the collider gridcell->index map, sorted by gridcell
                mDeviceColliderCellStart,                   // input:  At which index in mDeviceMapColliderIndex does cell X start?
                mDeviceColliderCellEnd,                     // input:  At which index in mDeviceMapColliderIndex does cell X end?

                mParametersSimulation->particleCount,        // input:  How many particles to collide against other particles (one thread per particle)
                mParametersSimulation->gridParticleSystem.cells.x * mParametersSimulation->gridParticleSystem.cells.y * mParametersSimulation->gridParticleSystem.cells.z  // input: Number of grid cells
                );

    //showCollisionPositions();

    //qDebug() << __PRETTY_FUNCTION__ << "9: colliding particles finished at" << startTime.elapsed();

    // Unmap at end here to avoid unnecessary graphics/CUDA context switch.
    // Once unmapped, the resource may not be accessed by CUDA until they
    // are mapped again. This function provides the synchronization guarantee
    // that any CUDA work issued  before ::cudaGraphicsUnmapResources()
    // will complete before any subsequently issued graphics work begins.
    cudaGraphicsUnmapResources(1, &mCudaVboResourceParticlePositions, 0);

    size_t memTotal, memFree;
    cudaMemGetInfo(&memFree, &memTotal);
    //qDebug() << __PRETTY_FUNCTION__ << "finished," << startTime.elapsed() << "ms, fps:" << 1000.0f/startTime.elapsed() << "free mem:" << memFree / 1048576;
}