Пример #1
0
/** Run the actual main loop.
 */
void MainLoop::run()
{
    IrrlichtDevice* device = irr_driver->getDevice();

    m_curr_time = device->getTimer()->getRealTime();
    while(!m_abort)
    {
        PROFILER_PUSH_CPU_MARKER("Main loop", 0xFF, 0x00, 0xF7);
        
        m_prev_time = m_curr_time;
        float dt   = getLimitedDt();

        network_manager->update(dt);

        if (World::getWorld())  // race is active if world exists
        {
            // Busy wait if race_manager is active (i.e. creating of world is done)
            // till all clients have reached this state.
            if (network_manager->getState()==NetworkManager::NS_READY_SET_GO_BARRIER) continue;
            updateRace(dt);
        }   // if race is active

        // We need to check again because update_race may have requested
        // the main loop to abort; and it's not a good idea to continue
        // since the GUI engine is no more to be called then.
        // Also only do music, input, and graphics update if graphics are
        // enabled.
        if (!m_abort && !ProfileWorld::isNoGraphics())
        {
            PROFILER_PUSH_CPU_MARKER("Music manager update", 0x7F, 0x00, 0x00);
            music_manager->update(dt);
            PROFILER_POP_CPU_MARKER();
            
            PROFILER_PUSH_CPU_MARKER("Input manager update", 0x00, 0x7F, 0x00);
            input_manager->update(dt);
            PROFILER_POP_CPU_MARKER();
            
            #ifdef ENABLE_WIIUSE
                wiimote_manager->update();
            #endif
            
            PROFILER_PUSH_CPU_MARKER("IrrDriver update", 0x00, 0x00, 0x7F);
            irr_driver->update(dt);
            PROFILER_POP_CPU_MARKER();
            
            PROFILER_SYNC_FRAME();
        }
        
        PROFILER_POP_CPU_MARKER();
    }  // while !m_exit

}   // run
Пример #2
0
/** Determines if a new state snapshot should be taken, and if so calls all
 *  rewinder to do so.
 *  \param ticks_not_used NUmber of physics time steps - should be 1.
 */
void RewindManager::update(int ticks_not_used)
{
    // FIXME: rename ticks_not_used
    if (!m_enable_rewind_manager ||
        m_all_rewinder.size() == 0 ||
        m_is_rewinding)  return;

    int ticks = World::getWorld()->getTicksSinceStart();

    m_not_rewound_ticks.store(ticks, std::memory_order_relaxed);

    if (!shouldSaveState(ticks))
        return;

    // Save state, remove expired rewinder first
    clearExpiredRewinder();
    if (NetworkConfig::get()->isClient())
    {
        auto& ret = m_local_state[ticks];
        for (auto& p : m_all_rewinder)
        {
            if (auto r = p.second.lock())
                ret.push_back(r->getLocalStateRestoreFunction());
        }
    }
    else
    {
        saveState();
        PROFILER_PUSH_CPU_MARKER("RewindManager - send state", 0x20, 0x7F, 0x40);
        if (auto gp = GameProtocol::lock())
            gp->sendState();
    }
    PROFILER_POP_CPU_MARKER();
}   // update
Пример #3
0
/** Saves a state using the GameProtocol function to combine several
 *  independent rewinders to write one state.
 */
void RewindManager::saveState()
{
    PROFILER_PUSH_CPU_MARKER("RewindManager - save state", 0x20, 0x7F, 0x20);
    auto gp = GameProtocol::lock();
    if (!gp)
        return;
    gp->startNewState();

    m_overall_state_size = 0;
    std::vector<std::string> rewinder_using;

    for (auto& p : m_all_rewinder)
    {
        // TODO: check if it's worth passing in a sufficiently large buffer from
        // GameProtocol - this would save the copy operation.
        BareNetworkString* buffer = NULL;
        if (auto r = p.second.lock())
            buffer = r->saveState(&rewinder_using);
        if (buffer != NULL)
        {
            m_overall_state_size += buffer->size();
            gp->addState(buffer);
        }
        delete buffer;    // buffer can be freed
    }
    gp->finalizeState(rewinder_using);
    PROFILER_POP_CPU_MARKER();
}   // saveState
Пример #4
0
/** Returns the current dt, which guarantees a limited frame rate. If dt is
 *  too low (the frame rate too high), the process will sleep to reach the
 *  maxium frame rate.
 */
float MainLoop::getLimitedDt()
{
    IrrlichtDevice* device = irr_driver->getDevice();
    m_prev_time = m_curr_time;

    float dt;  // needed outside of the while loop
    while( 1 )
    {
        m_curr_time = device->getTimer()->getRealTime();
        dt = (float)(m_curr_time - m_prev_time);

        // don't allow the game to run slower than a certain amount.
        // when the computer can't keep it up, slow down the shown time instead
        static const float max_elapsed_time = 3.0f*1.0f/60.0f*1000.0f; /* time 3 internal substeps take */
        if(dt > max_elapsed_time) dt=max_elapsed_time;

        // Throttle fps if more than maximum, which can reduce
        // the noise the fan on a graphics card makes.
        // When in menus, reduce FPS much, it's not necessary to push to the maximum for plain menus
        const int max_fps = (StateManager::get()->throttleFPS() ? 30 : UserConfigParams::m_max_fps);
        const int current_fps = (int)(1000.0f/dt);
        if (m_throttle_fps && current_fps > max_fps && !ProfileWorld::isProfileMode())
        {
            int wait_time = 1000/max_fps - 1000/current_fps;
            if(wait_time < 1) wait_time = 1;

            PROFILER_PUSH_CPU_MARKER("Throttle framerate", 0, 0, 0);
            StkTime::sleep(wait_time);
            PROFILER_POP_CPU_MARKER();
        }
        else break;
    }
    dt *= 0.001f;
    return dt;
}   // getLimitedDt
/** Determines if a new state snapshot should be taken, and if so calls all
 *  rewinder to do so.
 *  \param ticks_not_used NUmber of physics time steps - should be 1.
 */
void RewindManager::update(int ticks_not_used)
{
    // FIXME: rename ticks_not_used
    if (!m_enable_rewind_manager ||
        m_all_rewinder.size() == 0 ||
        m_is_rewinding)  return;

    float time = World::getWorld()->getTime();
    int ticks = World::getWorld()->getTimeTicks();

    m_not_rewound_ticks = ticks;

    // Clients don't save state, so they just exit.
    if (NetworkConfig::get()->isClient() ||
        ticks - m_last_saved_state < m_state_frequency)
    {
        return;
    }

    // Save state
    saveState(/**allow_local_save*/false);
    PROFILER_PUSH_CPU_MARKER("RewindManager - send state", 0x20, 0x7F, 0x40);
    GameProtocol::lock()->sendState();
    PROFILER_POP_CPU_MARKER();
    m_last_saved_state = ticks;
}   // update
/** Replays all events from the last event played till the specified time.
 *  \param world_ticks Up to (and inclusive) which time events will be replayed.
 *  \param ticks Number of time steps - should be 1.
 */
void RewindManager::playEventsTill(int world_ticks, int *ticks)
{
    bool needs_rewind;
    int rewind_ticks;

    // Merge in all network events that have happened at the current
    // time step.
    // merge and that have happened before the current time (which will
    // be getTime()+dt - world time has not been updated yet).
    m_rewind_queue.mergeNetworkData(world_ticks, &needs_rewind, &rewind_ticks);

    if (needs_rewind)
    {
        Log::setPrefix("Rewind");
        PROFILER_PUSH_CPU_MARKER("Rewind", 128, 128, 128);
        rewindTo(rewind_ticks, world_ticks);
        // This should replay everything up to 'now'
        assert(World::getWorld()->getTimeTicks() == world_ticks);
        PROFILER_POP_CPU_MARKER();
        Log::setPrefix("");
    }

    assert(!m_is_rewinding);
    if (m_rewind_queue.isEmpty()) return;

    // This is necessary to avoid that rewinding an event will store the 
    // event again as a seemingly new event.
    m_is_rewinding = true;

    // Now play all events that happened at the current time stamp.
    m_rewind_queue.replayAllEvents(world_ticks);

    m_is_rewinding = false;
}   // playEventsTill
Пример #7
0
/** Returns the current dt, which guarantees a limited frame rate. If dt is
 *  too low (the frame rate too high), the process will sleep to reach the
 *  maxium frame rate.
 */
float MainLoop::getLimitedDt()
{
    // In profile mode without graphics, run with a fixed dt of 1/60
    if (ProfileWorld::isProfileMode() && ProfileWorld::isNoGraphics())
    {
        return 1.0f/60.0f;
    }

    IrrlichtDevice* device = irr_driver->getDevice();
    m_prev_time = m_curr_time;

    float dt;  // needed outside of the while loop
    while( 1 )
    {
        m_curr_time = device->getTimer()->getRealTime();
        dt = (float)(m_curr_time - m_prev_time);
        const World* const world = World::getWorld();
        if (UserConfigParams::m_fps_debug && world)
        {
            const LinearWorld *lw = dynamic_cast<const LinearWorld*>(world);
            if (lw)
            {
                Log::verbose("fps", "time %f distance %f dt %f fps %f",
                             lw->getTime(),
                             lw->getDistanceDownTrackForKart(0),
                             dt*0.001f, 1000.0f / dt);
            }
            else
            {
                Log::verbose("fps", "time %f dt %f fps %f",
                             world->getTime(), dt*0.001f, 1000.0f / dt);
            }

        }

        // don't allow the game to run slower than a certain amount.
        // when the computer can't keep it up, slow down the shown time instead
        static const float max_elapsed_time = 3.0f*1.0f/60.0f*1000.0f; /* time 3 internal substeps take */
        if(dt > max_elapsed_time) dt=max_elapsed_time;

        // Throttle fps if more than maximum, which can reduce
        // the noise the fan on a graphics card makes.
        // When in menus, reduce FPS much, it's not necessary to push to the maximum for plain menus
        const int max_fps = (StateManager::get()->throttleFPS() ? 30 : UserConfigParams::m_max_fps);
        const int current_fps = (int)(1000.0f/dt);
        if (m_throttle_fps && current_fps > max_fps && !ProfileWorld::isProfileMode())
        {
            int wait_time = 1000/max_fps - 1000/current_fps;
            if(wait_time < 1) wait_time = 1;

            PROFILER_PUSH_CPU_MARKER("Throttle framerate", 0, 0, 0);
            StkTime::sleep(wait_time);
            PROFILER_POP_CPU_MARKER();
        }
        else break;
    }
    dt *= 0.001f;
    return dt;
}   // getLimitedDt
Пример #8
0
 /** Prepare draw calls before scene rendering
 */
void DrawCalls::prepareDrawCalls(scene::ICameraSceneNode *camnode)
{
    CPUParticleManager::getInstance()->reset();
    TextBillboardDrawer::reset();
    PROFILER_PUSH_CPU_MARKER("- culling", 0xFF, 0xFF, 0x0);
    SP::prepareDrawCalls();
    parseSceneManager(
        irr_driver->getSceneManager()->getRootSceneNode()->getChildren(),
        camnode);
    SP::handleDynamicDrawCall();
    SP::updateModelMatrix();
    PROFILER_POP_CPU_MARKER();

    PROFILER_PUSH_CPU_MARKER("- cpu particle generation", 0x2F, 0x1F, 0x11);
    CPUParticleManager::getInstance()->generateAll();
    PROFILER_POP_CPU_MARKER();

    // Add a 1 s timeout
    if (m_sync != 0)
    {
        PROFILER_PUSH_CPU_MARKER("- Sync Stall", 0xFF, 0x0, 0x0);
        GLenum reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
        if (reason != GL_ALREADY_SIGNALED)
        {
            do
            {
                reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000000);
            }
            while (reason == GL_TIMEOUT_EXPIRED);
        }
        glDeleteSync(m_sync);
        m_sync = 0;
        PROFILER_POP_CPU_MARKER();
    }

    PROFILER_PUSH_CPU_MARKER("- particle and text billboard upload", 0x3F,
        0x03, 0x61);
    CPUParticleManager::getInstance()->uploadAll();
    TextBillboardDrawer::updateAll();
    PROFILER_POP_CPU_MARKER();

    PROFILER_PUSH_CPU_MARKER("- SP::upload instance and skinning matrices",
        0xFF, 0x0, 0xFF);
    SP::uploadAll();
    PROFILER_POP_CPU_MARKER();
}
Пример #9
0
/** In network games this update function is called instead of
 *  World::updateWorld(). 
 *  \param ticks Number of physics time steps - should be 1.
 *  \param fast_forward If true, then only rewinders in network will be
 *  updated, but not the physics.
 */
void RaceEventManager::update(int ticks, bool fast_forward)
{
    // Replay all recorded events up to the current time
    // This might adjust dt - if a new state is being played, the dt is
    // determined from the last state till 'now'
    PROFILER_PUSH_CPU_MARKER("RaceEvent:play event", 100, 100, 100);
    RewindManager::get()->playEventsTill(World::getWorld()->getTicksSinceStart(),
                                         fast_forward);
    PROFILER_POP_CPU_MARKER();
    if (!fast_forward)
        World::getWorld()->updateWorld(ticks);
}   // update
Пример #10
0
/** Updates the physics, all karts, the track, and projectile manager.
 *  \param dt Time step size.
 */
void World::update(float dt)
{
#ifdef DEBUG
    assert(m_magic_number == 0xB01D6543);
#endif


    PROFILER_PUSH_CPU_MARKER("World::update()", 0x00, 0x7F, 0x00);

#if MEASURE_FPS
    static float time = 0.0f;
    time += dt;
    if (time > 5.0f)
    {
        time -= 5.0f;
        printf("%i\n",irr_driver->getVideoDriver()->getFPS());
    }
#endif

    history->update(dt);
    if(ReplayRecorder::get()) ReplayRecorder::get()->update(dt);
    if(ReplayPlay::get()) ReplayPlay::get()->update(dt);
    if(history->replayHistory()) dt=history->getNextDelta();
    WorldStatus::update(dt);

    if (!history->dontDoPhysics())
    {
        m_physics->update(dt);
    }

    const int kart_amount = m_karts.size();
    for (int i = 0 ; i < kart_amount; ++i)
    {
        // Update all karts that are not eliminated
        if(!m_karts[i]->isEliminated()) m_karts[i]->update(dt) ;
    }

    for(unsigned int i=0; i<Camera::getNumCameras(); i++)
    {
        Camera::getCamera(i)->update(dt);
    }

    projectile_manager->update(dt);

    PROFILER_POP_CPU_MARKER();

#ifdef DEBUG
    assert(m_magic_number == 0xB01D6543);
#endif
}   // update
/** Saves a local state using the GameProtocol function to combine several
 *  independent rewinders to write one state. Typically only the server needs
 *  to save a state (which is then send to the clients), except that each
 *  client needs one initial state (in case that it receives an event from
 *  a client before a state from the serer).
 *  \param allow_local_save Do a local save.
 */
void RewindManager::saveState(bool local_save)
{
    PROFILER_PUSH_CPU_MARKER("RewindManager - save state", 0x20, 0x7F, 0x20);
    GameProtocol::lock()->startNewState(local_save);
    AllRewinder::const_iterator rewinder;
    for (rewinder = m_all_rewinder.begin(); rewinder != m_all_rewinder.end(); ++rewinder)
    {
        // TODO: check if it's worth passing in a sufficiently large buffer from
        // GameProtocol - this would save the copy operation.
        BareNetworkString *buffer = (*rewinder)->saveState();
        if (buffer && buffer->size() >= 0)
        {
            m_overall_state_size += buffer->size();
            GameProtocol::lock()->addState(buffer);
        }   // size >= 0
        delete buffer;    // buffer can be freed
    }
    PROFILER_POP_CPU_MARKER();
}   // saveState
/** Updates the physics, all karts, the track, and projectile manager.
 *  \param dt Time step size.
 */
void World::update(float dt)
{
    PROFILER_PUSH_CPU_MARKER("World::update()", 0x00, 0x7F, 0x00);
    
#if MEASURE_FPS
    static float time = 0.0f;
    time += dt;
    if (time > 5.0f)
    {
        time -= 5.0f;
        printf("%i\n",irr_driver->getVideoDriver()->getFPS());
    }
#endif

    history->update(dt);
    if(ReplayRecorder::get()) ReplayRecorder::get()->update(dt);
    if(ReplayPlay::get()) ReplayPlay::get()->update(dt);
    if(history->replayHistory()) dt=history->getNextDelta();
    WorldStatus::update(dt);
    // Clear race state so that new information can be stored
    race_state->clear();

    if(network_manager->getMode()!=NetworkManager::NW_CLIENT &&
        !history->dontDoPhysics())
    {
        m_physics->update(dt);
    }

    const int kart_amount = m_karts.size();
    for (int i = 0 ; i < kart_amount; ++i)
    {
        // Update all karts that are not eliminated
        if(!m_karts[i]->isEliminated()) m_karts[i]->update(dt) ;
    }

    projectile_manager->update(dt);
    
    PROFILER_POP_CPU_MARKER();
}   // update
Пример #13
0
void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned pointlightcount, std::vector<GlowData>& glows, float dt, bool hasShadow, bool forceRTT)
{
    glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedObject::ViewProjectionMatrixesUBO);

    // Shadows
    {
        PROFILER_PUSH_CPU_MARKER("- Shadow", 0x30, 0x6F, 0x90);
        ScopedGPUTimer Timer(getGPUTimer(Q_SHADOWS));
        // To avoid wrong culling, use the largest view possible
        m_scene_manager->setActiveCamera(m_suncam);
        if (!m_mipviz && !m_wireframe && UserConfigParams::m_dynamic_lights &&
            UserConfigParams::m_shadows && !irr_driver->needUBOWorkaround() && hasShadow)
            renderShadows();
        m_scene_manager->setActiveCamera(camnode);
        PROFILER_POP_CPU_MARKER();
    }

    PROFILER_PUSH_CPU_MARKER("- Solid Pass 1", 0xFF, 0x00, 0x00);
    renderSolidFirstPass();
    PROFILER_POP_CPU_MARKER();



    // Lights
    {
        PROFILER_PUSH_CPU_MARKER("- Light", 0x00, 0xFF, 0x00);
        renderLights(pointlightcount);
        PROFILER_POP_CPU_MARKER();
    }

    // Handle SSAO
    {
        PROFILER_PUSH_CPU_MARKER("- SSAO", 0xFF, 0xFF, 0x00);
        ScopedGPUTimer Timer(getGPUTimer(Q_SSAO));
        if (UserConfigParams::m_ssao)
            renderSSAO();
        PROFILER_POP_CPU_MARKER();
    }

    PROFILER_PUSH_CPU_MARKER("- Solid Pass 2", 0x00, 0x00, 0xFF);
    if (!UserConfigParams::m_dynamic_lights && ! forceRTT)
    {
        glEnable(GL_FRAMEBUFFER_SRGB);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }
    else
        m_rtts->getFBO(FBO_COLORS).Bind();
    renderSolidSecondPass();
    PROFILER_POP_CPU_MARKER();

    if (UserConfigParams::m_dynamic_lights && World::getWorld() != NULL &&
        World::getWorld()->isFogEnabled())
    {
        PROFILER_PUSH_CPU_MARKER("- Fog", 0xFF, 0x00, 0x00);
        m_post_processing->renderFog();
        PROFILER_POP_CPU_MARKER();
    }

    PROFILER_PUSH_CPU_MARKER("- Skybox", 0xFF, 0x00, 0xFF);
    renderSkybox(camnode);
    PROFILER_POP_CPU_MARKER();

    if (getRH())
    {
        glEnable(GL_PROGRAM_POINT_SIZE);
        m_rtts->getFBO(FBO_COLORS).Bind();
        glUseProgram(FullScreenShader::RHDebug::Program);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_3D, m_rtts->getRH().getRTT()[0]);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_3D, m_rtts->getRH().getRTT()[1]);
        glActiveTexture(GL_TEXTURE2);
        glBindTexture(GL_TEXTURE_3D, m_rtts->getRH().getRTT()[2]);
        FullScreenShader::RHDebug::setUniforms(rh_matrix, rh_extend, 0, 1, 2);
        glDrawArrays(GL_POINTS, 0, 32 * 16 * 32);
        glDisable(GL_PROGRAM_POINT_SIZE);
    }

    if (getGI())
    {
        m_rtts->getFBO(FBO_COLORS).Bind();
        m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]);
    }

    PROFILER_PUSH_CPU_MARKER("- Glow", 0xFF, 0xFF, 0x00);
    // Render anything glowing.
    if (!m_mipviz && !m_wireframe && UserConfigParams::m_glow)
    {
        irr_driver->setPhase(GLOW_PASS);
        renderGlow(glows);
    } // end glow
    PROFILER_POP_CPU_MARKER();

    PROFILER_PUSH_CPU_MARKER("- Lensflare/godray", 0x00, 0xFF, 0xFF);
    computeSunVisibility();
    PROFILER_POP_CPU_MARKER();

    // Render transparent
    {
        PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(getGPUTimer(Q_TRANSPARENT));
        renderTransparent();
        PROFILER_POP_CPU_MARKER();
    }

    // Render particles
    {
        PROFILER_PUSH_CPU_MARKER("- Particles", 0xFF, 0xFF, 0x00);
        ScopedGPUTimer Timer(getGPUTimer(Q_PARTICLES));
        renderParticles();
        PROFILER_POP_CPU_MARKER();
    }
    if (!UserConfigParams::m_dynamic_lights && !forceRTT)
    {
        glDisable(GL_FRAMEBUFFER_SRGB);
        glDisable(GL_DEPTH_TEST);
        glDepthMask(GL_FALSE);
        return;
    }

    // Ensure that no object will be drawn after that by using invalid pass
    irr_driver->setPhase(PASS_COUNT);
}
Пример #14
0
void IrrDriver::renderFixed(float dt)
{
    World *world = World::getWorld(); // Never NULL.

    m_video_driver->beginScene(/*backBuffer clear*/ true, /*zBuffer*/ true,
                               world->getClearColor());

    irr_driver->getVideoDriver()->enableMaterial2D();

    RaceGUIBase *rg = world->getRaceGUI();
    if (rg) rg->update(dt);


    for(unsigned int i=0; i<Camera::getNumCameras(); i++)
    {
        Camera *camera = Camera::getCamera(i);

        std::ostringstream oss;
        oss << "drawAll() for kart " << i;
        PROFILER_PUSH_CPU_MARKER(oss.str().c_str(), (i+1)*60,
                                 0x00, 0x00);
        camera->activate();
        rg->preRenderCallback(camera);   // adjusts start referee

        m_renderpass = ~0;
        m_scene_manager->drawAll();

        PROFILER_POP_CPU_MARKER();

        // Note that drawAll must be called before rendering
        // the bullet debug view, since otherwise the camera
        // is not set up properly. This is only used for
        // the bullet debug view.
        if (UserConfigParams::m_artist_debug_mode)
            World::getWorld()->getPhysics()->draw();
    }   // for i<world->getNumKarts()

    // Set the viewport back to the full screen for race gui
    m_video_driver->setViewPort(core::recti(0, 0,
                                            UserConfigParams::m_width,
                                            UserConfigParams::m_height));

    for(unsigned int i=0; i<Camera::getNumCameras(); i++)
    {
        Camera *camera = Camera::getCamera(i);
        std::ostringstream oss;
        oss << "renderPlayerView() for kart " << i;

        PROFILER_PUSH_CPU_MARKER(oss.str().c_str(), 0x00, 0x00, (i+1)*60);
        rg->renderPlayerView(camera, dt);
        PROFILER_POP_CPU_MARKER();

    }  // for i<getNumKarts

    // Either render the gui, or the global elements of the race gui.
    GUIEngine::render(dt);

    // Render the profiler
    if(UserConfigParams::m_profiler_enabled)
    {
        PROFILER_DRAW();
    }

#ifdef DEBUG
    drawDebugMeshes();
#endif

    m_video_driver->endScene();
}
Пример #15
0
void IrrDriver::renderGLSL(float dt)
{
    BoundingBoxes.clear();
    World *world = World::getWorld(); // Never NULL.

    Track *track = world->getTrack();

    for (unsigned i = 0; i < PowerupManager::POWERUP_MAX; i++)
    {
        scene::IMesh *mesh = powerup_manager->m_all_meshes[i];
        if (!mesh)
            continue;
        for (unsigned j = 0; j < mesh->getMeshBufferCount(); j++)
        {
            scene::IMeshBuffer *mb = mesh->getMeshBuffer(j);
            if (!mb)
                continue;
            for (unsigned k = 0; k < 4; k++)
            {
                video::ITexture *tex = mb->getMaterial().getTexture(k);
                if (!tex)
                    continue;
                compressTexture(tex, true);
            }
        }
    }


    // Overrides
    video::SOverrideMaterial &overridemat = m_video_driver->getOverrideMaterial();
    overridemat.EnablePasses = scene::ESNRP_SOLID | scene::ESNRP_TRANSPARENT;
    overridemat.EnableFlags = 0;

    if (m_wireframe)
    {
        overridemat.Material.Wireframe = 1;
        overridemat.EnableFlags |= video::EMF_WIREFRAME;
    }
    if (m_mipviz)
    {
        overridemat.Material.MaterialType = m_shaders->getShader(ES_MIPVIZ);
        overridemat.EnableFlags |= video::EMF_MATERIAL_TYPE;
        overridemat.EnablePasses = scene::ESNRP_SOLID;
    }

    // Get a list of all glowing things. The driver's list contains the static ones,
    // here we add items, as they may disappear each frame.
    std::vector<GlowData> glows = m_glowing;

    ItemManager * const items = ItemManager::get();
    const u32 itemcount = items->getNumberOfItems();
    u32 i;

    for (i = 0; i < itemcount; i++)
    {
        Item * const item = items->getItem(i);
        if (!item) continue;
        const Item::ItemType type = item->getType();

        if (type != Item::ITEM_NITRO_BIG && type != Item::ITEM_NITRO_SMALL &&
            type != Item::ITEM_BONUS_BOX && type != Item::ITEM_BANANA && type != Item::ITEM_BUBBLEGUM)
            continue;

        LODNode * const lod = (LODNode *) item->getSceneNode();
        if (!lod->isVisible()) continue;

        const int level = lod->getLevel();
        if (level < 0) continue;

        scene::ISceneNode * const node = lod->getAllNodes()[level];
        node->updateAbsolutePosition();

        GlowData dat;
        dat.node = node;

        dat.r = 1.0f;
        dat.g = 1.0f;
        dat.b = 1.0f;

        const video::SColorf &c = ItemManager::getGlowColor(type);
        dat.r = c.getRed();
        dat.g = c.getGreen();
        dat.b = c.getBlue();

        glows.push_back(dat);
    }

    // Start the RTT for post-processing.
    // We do this before beginScene() because we want to capture the glClear()
    // because of tracks that do not have skyboxes (generally add-on tracks)
    m_post_processing->begin();

    RaceGUIBase *rg = world->getRaceGUI();
    if (rg) rg->update(dt);

    if (!CVS->isDefferedEnabled())
    {
        SColor clearColor(0, 150, 150, 150);
        if (World::getWorld() != NULL)
            clearColor = World::getWorld()->getClearColor();

        glClear(GL_COLOR_BUFFER_BIT);
        glDepthMask(GL_TRUE);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        glClearColor(clearColor.getRed() / 255.f, clearColor.getGreen() / 255.f,
            clearColor.getBlue() / 255.f, clearColor.getAlpha() / 255.f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    }

    for(unsigned int cam = 0; cam < Camera::getNumCameras(); cam++)
    {
        Camera * const camera = Camera::getCamera(cam);
        scene::ICameraSceneNode * const camnode = camera->getCameraSceneNode();

        std::ostringstream oss;
        oss << "drawAll() for kart " << cam;
        PROFILER_PUSH_CPU_MARKER(oss.str().c_str(), (cam+1)*60,
                                 0x00, 0x00);
        camera->activate(!CVS->isDefferedEnabled());
        rg->preRenderCallback(camera);   // adjusts start referee
        m_scene_manager->setActiveCamera(camnode);

        const core::recti &viewport = camera->getViewport();

        if (World::getWorld() && World::getWorld()->getTrack()->hasShadows() && !SphericalHarmonicsTextures.empty())
            irr_driver->getSceneManager()->setAmbientLight(SColor(0, 0, 0, 0));

        // TODO: put this outside of the rendering loop
        if (!m_skybox_ready)
        {
            prepareSkybox();
            m_skybox_ready = true;
        }
        if (!CVS->isDefferedEnabled())
            glEnable(GL_FRAMEBUFFER_SRGB);

        PROFILER_PUSH_CPU_MARKER("Update Light Info", 0xFF, 0x0, 0x0);
        unsigned plc = UpdateLightsInfo(camnode, dt);
        PROFILER_POP_CPU_MARKER();
        PROFILER_PUSH_CPU_MARKER("UBO upload", 0x0, 0xFF, 0x0);
        computeMatrixesAndCameras(camnode, viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X, viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y);
        uploadLightingData();
        PROFILER_POP_CPU_MARKER();
        renderScene(camnode, plc, glows, dt, track->hasShadows(), false);

        // Render bounding boxes
        if (irr_driver->getBoundingBoxesViz())
        {
            glUseProgram(UtilShader::ColoredLine::getInstance()->Program);
            glBindVertexArray(UtilShader::ColoredLine::getInstance()->vao);
            glBindBuffer(GL_ARRAY_BUFFER, UtilShader::ColoredLine::getInstance()->vbo);
            UtilShader::ColoredLine::getInstance()->setUniforms(SColor(255, 255, 0, 0));
            const float *tmp = BoundingBoxes.data();
            for (unsigned int i = 0; i < BoundingBoxes.size(); i += 1024 * 6)
            {
                unsigned count = MIN2((int)BoundingBoxes.size() - i, 1024 * 6);
                glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(float), &tmp[i]);

                glDrawArrays(GL_LINES, 0, count / 3);
            }
        }

        // Debug physic
        // Note that drawAll must be called before rendering
        // the bullet debug view, since otherwise the camera
        // is not set up properly. This is only used for
        // the bullet debug view.
        if (UserConfigParams::m_artist_debug_mode)
            World::getWorld()->getPhysics()->draw();
        if (world != NULL && world->getPhysics() != NULL)
        {
            IrrDebugDrawer* debug_drawer = world->getPhysics()->getDebugDrawer();
            if (debug_drawer != NULL && debug_drawer->debugEnabled())
            {
                const std::map<video::SColor, std::vector<float> >& lines = debug_drawer->getLines();
                std::map<video::SColor, std::vector<float> >::const_iterator it;

                glUseProgram(UtilShader::ColoredLine::getInstance()->Program);
                glBindVertexArray(UtilShader::ColoredLine::getInstance()->vao);
                glBindBuffer(GL_ARRAY_BUFFER, UtilShader::ColoredLine::getInstance()->vbo);
                for (it = lines.begin(); it != lines.end(); it++)
                {
                    UtilShader::ColoredLine::getInstance()->setUniforms(it->first);
                    const std::vector<float> &vertex = it->second;
                    const float *tmp = vertex.data();
                    for (unsigned int i = 0; i < vertex.size(); i += 1024 * 6)
                    {
                        unsigned count = MIN2((int)vertex.size() - i, 1024 * 6);
                        glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(float), &tmp[i]);

                        glDrawArrays(GL_LINES, 0, count / 3);
                    }
                }
                glUseProgram(0);
                glBindVertexArray(0);
            }
        }

        // Render the post-processed scene
        if (CVS->isDefferedEnabled())
        {
            bool isRace = StateManager::get()->getGameState() == GUIEngine::GAME;
            FrameBuffer *fbo = m_post_processing->render(camnode, isRace);

            if (irr_driver->getNormals())
                irr_driver->getFBO(FBO_NORMAL_AND_DEPTHS).BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
            else if (irr_driver->getSSAOViz())
            {
                glBindFramebuffer(GL_FRAMEBUFFER, 0);
                glViewport(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
                m_post_processing->renderPassThrough(m_rtts->getFBO(FBO_HALF1_R).getRTT()[0], viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X, viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y);
            }
            else if (irr_driver->getRSM())
            {
                glBindFramebuffer(GL_FRAMEBUFFER, 0);
                glViewport(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
                m_post_processing->renderPassThrough(m_rtts->getRSM().getRTT()[0], viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X, viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y);
            }
            else if (irr_driver->getShadowViz())
            {
                renderShadowsDebug();
            }
            else
            {
                glEnable(GL_FRAMEBUFFER_SRGB);
                glBindFramebuffer(GL_FRAMEBUFFER, 0);
                if (CVS->isDefferedEnabled())
                    camera->activate();
                m_post_processing->renderPassThrough(fbo->getRTT()[0], viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X, viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y);
                glDisable(GL_FRAMEBUFFER_SRGB);
            }
        }
        // Save projection-view matrix for the next frame
        camera->setPreviousPVMatrix(m_ProjViewMatrix);

        PROFILER_POP_CPU_MARKER();
    }   // for i<world->getNumKarts()

    // Use full screen size
    float tmp[2];
    tmp[0] = float(m_actual_screen_size.Width);
    tmp[1] = float(m_actual_screen_size.Height);
    glBindBuffer(GL_UNIFORM_BUFFER, SharedObject::ViewProjectionMatrixesUBO);
    glBufferSubData(GL_UNIFORM_BUFFER, (16 * 9) * sizeof(float), 2 * sizeof(float), tmp);

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glUseProgram(0);

    // Set the viewport back to the full screen for race gui
    m_video_driver->setViewPort(core::recti(0, 0,
        irr_driver->getActualScreenSize().Width,
        irr_driver->getActualScreenSize().Height));

    for(unsigned int i=0; i<Camera::getNumCameras(); i++)
    {
        Camera *camera = Camera::getCamera(i);
        std::ostringstream oss;
        oss << "renderPlayerView() for kart " << i;

        PROFILER_PUSH_CPU_MARKER(oss.str().c_str(), 0x00, 0x00, (i+1)*60);
        rg->renderPlayerView(camera, dt);

        PROFILER_POP_CPU_MARKER();
    }  // for i<getNumKarts

    {
        ScopedGPUTimer Timer(getGPUTimer(Q_GUI));
        PROFILER_PUSH_CPU_MARKER("GUIEngine", 0x75, 0x75, 0x75);
        // Either render the gui, or the global elements of the race gui.
        GUIEngine::render(dt);
        PROFILER_POP_CPU_MARKER();
    }

    // Render the profiler
    if(UserConfigParams::m_profiler_enabled)
    {
        PROFILER_DRAW();
    }


#ifdef DEBUG
    drawDebugMeshes();
#endif


    PROFILER_PUSH_CPU_MARKER("EndSccene", 0x45, 0x75, 0x45);
    m_video_driver->endScene();
    PROFILER_POP_CPU_MARKER();

    getPostProcessing()->update(dt);
}
Пример #16
0
void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned pointlightcount, std::vector<GlowData>& glows, float dt, bool hasShadow, bool forceRTT)
{
    glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedObject::ViewProjectionMatrixesUBO);
    glBindBufferBase(GL_UNIFORM_BUFFER, 1, SharedObject::LightingDataUBO);
    m_scene_manager->setActiveCamera(camnode);

    PROFILER_PUSH_CPU_MARKER("- Draw Call Generation", 0xFF, 0xFF, 0xFF);
    PrepareDrawCalls(camnode);
    PROFILER_POP_CPU_MARKER();
    // Shadows
    {
        // To avoid wrong culling, use the largest view possible
        m_scene_manager->setActiveCamera(m_suncam);
        if (CVS->isDefferedEnabled() &&
            CVS->isShadowEnabled() && hasShadow)
        {
            PROFILER_PUSH_CPU_MARKER("- Shadow", 0x30, 0x6F, 0x90);
            renderShadows();
            PROFILER_POP_CPU_MARKER();
            if (CVS->isGlobalIlluminationEnabled())
            {
                PROFILER_PUSH_CPU_MARKER("- RSM", 0xFF, 0x0, 0xFF);
                renderRSM();
                PROFILER_POP_CPU_MARKER();
            }
        }
        m_scene_manager->setActiveCamera(camnode);

    }

    PROFILER_PUSH_CPU_MARKER("- Solid Pass 1", 0xFF, 0x00, 0x00);
    glDepthMask(GL_TRUE);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);
    glEnable(GL_CULL_FACE);
    if (CVS->isDefferedEnabled() || forceRTT)
    {
        m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).Bind();
        glClearColor(0., 0., 0., 0.);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        renderSolidFirstPass();
    }
    else
    {
        // We need a cleared depth buffer for some effect (eg particles depth blending)
        if (GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_FRAMEBUFFER_SRGB_WORKING))
            glDisable(GL_FRAMEBUFFER_SRGB);
        m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).Bind();
        // Bind() modifies the viewport. In order not to affect anything else,
        // the viewport is just reset here and not removed in Bind().
        const core::recti &vp = Camera::getActiveCamera()->getViewport();
        glViewport(vp.UpperLeftCorner.X,
                   irr_driver->getActualScreenSize().Height - vp.LowerRightCorner.Y,
                   vp.LowerRightCorner.X - vp.UpperLeftCorner.X,
                   vp.LowerRightCorner.Y - vp.UpperLeftCorner.Y);
        glClear(GL_DEPTH_BUFFER_BIT);
        if (GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_FRAMEBUFFER_SRGB_WORKING))
            glEnable(GL_FRAMEBUFFER_SRGB);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }
    PROFILER_POP_CPU_MARKER();



    // Lights
    {
        PROFILER_PUSH_CPU_MARKER("- Light", 0x00, 0xFF, 0x00);
        if (CVS->isDefferedEnabled())
            renderLights(pointlightcount, hasShadow);
        PROFILER_POP_CPU_MARKER();
    }

    // Handle SSAO
    {
        PROFILER_PUSH_CPU_MARKER("- SSAO", 0xFF, 0xFF, 0x00);
        ScopedGPUTimer Timer(getGPUTimer(Q_SSAO));
        if (UserConfigParams::m_ssao)
            renderSSAO();
        PROFILER_POP_CPU_MARKER();
    }

    PROFILER_PUSH_CPU_MARKER("- Solid Pass 2", 0x00, 0x00, 0xFF);
    if (CVS->isDefferedEnabled() || forceRTT)
    {
        m_rtts->getFBO(FBO_COLORS).Bind();
        SColor clearColor(0, 150, 150, 150);
        if (World::getWorld() != NULL)
            clearColor = World::getWorld()->getClearColor();

        glClearColor(clearColor.getRed() / 255.f, clearColor.getGreen() / 255.f,
            clearColor.getBlue() / 255.f, clearColor.getAlpha() / 255.f);
        glClear(GL_COLOR_BUFFER_BIT);
        glDepthMask(GL_FALSE);
    }
    renderSolidSecondPass();
    PROFILER_POP_CPU_MARKER();

    if (getNormals())
    {
        m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).Bind();
        renderNormalsVisualisation();
        m_rtts->getFBO(FBO_COLORS).Bind();
    }

    // Render ambient scattering
    if (CVS->isDefferedEnabled() && World::getWorld() != NULL &&
        World::getWorld()->isFogEnabled())
    {
        PROFILER_PUSH_CPU_MARKER("- Ambient scatter", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(getGPUTimer(Q_FOG));
        renderAmbientScatter();
        PROFILER_POP_CPU_MARKER();
    }

    {
        PROFILER_PUSH_CPU_MARKER("- Skybox", 0xFF, 0x00, 0xFF);
        ScopedGPUTimer Timer(getGPUTimer(Q_SKYBOX));
        renderSkybox(camnode);
        PROFILER_POP_CPU_MARKER();
    }

    // Render discrete lights scattering
    if (CVS->isDefferedEnabled() && World::getWorld() != NULL &&
        World::getWorld()->isFogEnabled())
    {
        PROFILER_PUSH_CPU_MARKER("- PointLight Scatter", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(getGPUTimer(Q_FOG));
        renderLightsScatter(pointlightcount);
        PROFILER_POP_CPU_MARKER();
    }

    if (getRH())
    {
        glDisable(GL_BLEND);
        m_rtts->getFBO(FBO_COLORS).Bind();
        m_post_processing->renderRHDebug(m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2], rh_matrix, rh_extend);
    }

    if (getGI())
    {
        glDisable(GL_BLEND);
        m_rtts->getFBO(FBO_COLORS).Bind();
        m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]);
    }

    PROFILER_PUSH_CPU_MARKER("- Glow", 0xFF, 0xFF, 0x00);
    // Render anything glowing.
    if (!m_mipviz && !m_wireframe && UserConfigParams::m_glow)
    {
        ScopedGPUTimer Timer(getGPUTimer(Q_GLOW));
        irr_driver->setPhase(GLOW_PASS);
        renderGlow(glows);
    } // end glow
    PROFILER_POP_CPU_MARKER();

    PROFILER_PUSH_CPU_MARKER("- Lensflare/godray", 0x00, 0xFF, 0xFF);
    computeSunVisibility();
    PROFILER_POP_CPU_MARKER();

    // Render transparent
    {
        PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(getGPUTimer(Q_TRANSPARENT));
        renderTransparent();
        PROFILER_POP_CPU_MARKER();
    }

    m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);

    // Render particles
    {
        PROFILER_PUSH_CPU_MARKER("- Particles", 0xFF, 0xFF, 0x00);
        ScopedGPUTimer Timer(getGPUTimer(Q_PARTICLES));
        renderParticles();
        PROFILER_POP_CPU_MARKER();
    }
    if (!CVS->isDefferedEnabled() && !forceRTT)
    {
        glDisable(GL_FRAMEBUFFER_SRGB);
        glDisable(GL_DEPTH_TEST);
        glDepthMask(GL_FALSE);
        return;
    }

    // Ensure that no object will be drawn after that by using invalid pass
    irr_driver->setPhase(PASS_COUNT);
}
Пример #17
0
 /** Prepare draw calls before scene rendering
 * \param[out] solid_poly_count Total number of polygons in objects 
 *                              that will be rendered in this frame
 * \param[out] shadow_poly_count Total number of polygons for shadow
 *                               (rendered this frame)
 */
void DrawCalls::prepareDrawCalls( ShadowMatrices& shadow_matrices,
                                  scene::ICameraSceneNode *camnode,
                                  unsigned &solid_poly_count,
                                  unsigned &shadow_poly_count)
{
    m_wind_dir = getWindDir();
    clearLists();
    
    for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
    {
        m_solid_pass_mesh[Mat].clear();
        m_reflective_shadow_map_mesh[Mat].clear();
        for (unsigned i = 0; i < 4; i++)
            m_shadow_pass_mesh[i * Material::SHADERTYPE_COUNT + Mat].clear();
    }

    m_glow_pass_mesh.clear();
    m_deferred_update.clear();

    PROFILER_PUSH_CPU_MARKER("- culling", 0xFF, 0xFF, 0x0);
    parseSceneManager(
        irr_driver->getSceneManager()->getRootSceneNode()->getChildren(),
        &m_immediate_draw_list, camnode, shadow_matrices);
    PROFILER_POP_CPU_MARKER();

    // Add a 1 s timeout
    if (!m_sync)
        m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
    PROFILER_PUSH_CPU_MARKER("- Sync Stall", 0xFF, 0x0, 0x0);
    GLenum reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0);

    if (reason != GL_ALREADY_SIGNALED)
    {
        do
        {
            reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000000);
        } 
        while (reason == GL_TIMEOUT_EXPIRED);
    }
    glDeleteSync(m_sync);
    PROFILER_POP_CPU_MARKER();

    /*    switch (reason)
    {
    case GL_ALREADY_SIGNALED:
    printf("Already Signaled\n");
    break;
    case GL_TIMEOUT_EXPIRED:
    printf("Timeout Expired\n");
    break;
    case GL_CONDITION_SATISFIED:
    printf("Condition Satisfied\n");
    break;
    case GL_WAIT_FAILED:
    printf("Wait Failed\n");
    break;
    }*/

    PROFILER_PUSH_CPU_MARKER("- Animations/Buffer upload", 0x0, 0x0, 0x0);
    for (unsigned i = 0; i < m_deferred_update.size(); i++)
        m_deferred_update[i]->updateGL();
    PROFILER_POP_CPU_MARKER();

    if (!CVS->supportsIndirectInstancingRendering())
        return;

#if !defined(USE_GLES2)
    int enableOpenMP = 0;
    
    if (CVS->supportsAsyncInstanceUpload())
        enableOpenMP = 1;
    
    PROFILER_PUSH_CPU_MARKER("- Draw Command upload", 0xFF, 0x0, 0xFF);

#pragma omp parallel sections if(enableOpenMP)
    {
#pragma omp section
        {
            m_solid_cmd_buffer->fill(m_solid_pass_mesh);
        }
#pragma omp section
        {            
            m_glow_cmd_buffer->fill(&m_glow_pass_mesh);
        }
#pragma omp section
        {
            irr_driver->setPhase(SHADOW_PASS);
            m_shadow_cmd_buffer->fill(m_shadow_pass_mesh);
        }
#pragma omp section
        if (!shadow_matrices.isRSMMapAvail())
        {
            m_reflective_shadow_map_cmd_buffer->fill(m_reflective_shadow_map_mesh);
        }
    }
    PROFILER_POP_CPU_MARKER();
    solid_poly_count = m_solid_cmd_buffer->getPolyCount();
    shadow_poly_count = m_shadow_cmd_buffer->getPolyCount();    
    
    if (CVS->supportsAsyncInstanceUpload())
        glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
#endif // !defined(USE_GLES2)
}
Пример #18
0
void IrrDriver::renderGLSL(float dt)
{
    World *world = World::getWorld(); // Never NULL.

    // Overrides
    video::SOverrideMaterial &overridemat = m_video_driver->getOverrideMaterial();
    overridemat.EnablePasses = scene::ESNRP_SOLID | scene::ESNRP_TRANSPARENT;
    overridemat.EnableFlags = 0;

    if (m_wireframe)
    {
        overridemat.Material.Wireframe = 1;
        overridemat.EnableFlags |= video::EMF_WIREFRAME;
    }
    if (m_mipviz)
    {
        overridemat.Material.MaterialType = m_shaders->getShader(ES_MIPVIZ);
        overridemat.EnableFlags |= video::EMF_MATERIAL_TYPE;
        overridemat.EnablePasses = scene::ESNRP_SOLID;
    }

    // Get a list of all glowing things. The driver's list contains the static ones,
    // here we add items, as they may disappear each frame.
    std::vector<GlowData> glows = m_glowing;
    std::vector<GlowNode *> transparent_glow_nodes;

    ItemManager * const items = ItemManager::get();
    const u32 itemcount = items->getNumberOfItems();
    u32 i;

    // For each static node, give it a glow representation
    const u32 staticglows = glows.size();
    for (i = 0; i < staticglows; i++)
    {
        scene::ISceneNode * const node = glows[i].node;

        const float radius = (node->getBoundingBox().getExtent().getLength() / 2) * 2.0f;
        GlowNode * const repnode = new GlowNode(irr_driver->getSceneManager(), radius);
        repnode->setPosition(node->getTransformedBoundingBox().getCenter());
        transparent_glow_nodes.push_back(repnode);
    }

    for (i = 0; i < itemcount; i++)
    {
        Item * const item = items->getItem(i);
        if (!item) continue;
        const Item::ItemType type = item->getType();

        if (type != Item::ITEM_NITRO_BIG && type != Item::ITEM_NITRO_SMALL &&
            type != Item::ITEM_BONUS_BOX && type != Item::ITEM_BANANA && type != Item::ITEM_BUBBLEGUM)
            continue;

        LODNode * const lod = (LODNode *) item->getSceneNode();
        if (!lod->isVisible()) continue;

        const int level = lod->getLevel();
        if (level < 0) continue;

        scene::ISceneNode * const node = lod->getAllNodes()[level];
        node->updateAbsolutePosition();

        GlowData dat;
        dat.node = node;

        dat.r = 1.0f;
        dat.g = 1.0f;
        dat.b = 1.0f;

        const video::SColorf &c = ItemManager::getGlowColor(type);
        dat.r = c.getRed();
        dat.g = c.getGreen();
        dat.b = c.getBlue();

        glows.push_back(dat);

        // Push back its representation too
        const float radius = (node->getBoundingBox().getExtent().getLength() / 2) * 2.0f;
        GlowNode * const repnode = new GlowNode(irr_driver->getSceneManager(), radius);
        repnode->setPosition(node->getTransformedBoundingBox().getCenter());
        transparent_glow_nodes.push_back(repnode);
    }

    // Start the RTT for post-processing.
    // We do this before beginScene() because we want to capture the glClear()
    // because of tracks that do not have skyboxes (generally add-on tracks)
    m_post_processing->begin();
    m_video_driver->setRenderTarget(m_rtts->getRTT(RTT_COLOR), false, false);

    m_video_driver->beginScene(/*backBuffer clear*/ true, /*zBuffer*/ true,
                               world->getClearColor());

    // Clear normal and depth to zero
    m_video_driver->setRenderTarget(m_rtts->getRTT(RTT_NORMAL_AND_DEPTH), true, false, video::SColor(0,0,0,0));
    // Clear specular map to zero
    m_video_driver->setRenderTarget(m_rtts->getRTT(RTT_SPECULARMAP), true, false, video::SColor(0,0,0,0));

    irr_driver->getVideoDriver()->enableMaterial2D();
    RaceGUIBase *rg = world->getRaceGUI();
    if (rg) rg->update(dt);


    for(unsigned int cam = 0; cam < Camera::getNumCameras(); cam++)
    {
        Camera * const camera = Camera::getCamera(cam);
        scene::ICameraSceneNode * const camnode = camera->getCameraSceneNode();

#ifdef ENABLE_PROFILER
        std::ostringstream oss;
        oss << "drawAll() for kart " << cam << std::flush;
        PROFILER_PUSH_CPU_MARKER(oss.str().c_str(), (cam+1)*60,
                                 0x00, 0x00);
#endif
        camera->activate();
        rg->preRenderCallback(camera);   // adjusts start referee

        const u32 bgnodes = m_background.size();
/*        if (bgnodes)
        {
            // If there are background nodes (3d skybox), draw them now.
            m_video_driver->setRenderTarget(m_rtts->getRTT(RTT_COLOR), false, false);

            m_renderpass = scene::ESNRP_SKY_BOX;
            m_scene_manager->drawAll(m_renderpass);

            const video::SOverrideMaterial prev = overridemat;
            overridemat.Enabled = 1;
            overridemat.EnableFlags = video::EMF_MATERIAL_TYPE;
            overridemat.Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;

            for (i = 0; i < bgnodes; i++)
            {
                m_background[i]->setPosition(camnode->getPosition() * 0.97f);
                m_background[i]->updateAbsolutePosition();
                m_background[i]->render();
            }

            overridemat = prev;
            m_video_driver->setRenderTarget(m_rtts->getRTT(RTT_COLOR), false, true);
        }*/

        // Fire up the MRT
		irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH), false, false);
		PROFILER_PUSH_CPU_MARKER("- Solid Pass 1", 0xFF, 0x00, 0x00);
        m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_SOLID;
		glDepthFunc(GL_LEQUAL);
		glEnable(GL_DEPTH_TEST);
		glDisable(GL_ALPHA_TEST);
		glDepthMask(GL_TRUE);
		glDisable(GL_BLEND);
        irr_driver->setPhase(SOLID_NORMAL_AND_DEPTH_PASS);
        m_scene_manager->drawAll(m_renderpass);
        irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION));
        irr_driver->setViewMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW));
        irr_driver->genProjViewMatrix();

		PROFILER_POP_CPU_MARKER();

        // Todo : reenable glow and shadows
        //ShadowImportanceProvider * const sicb = (ShadowImportanceProvider *)
        //                                         irr_driver->getCallback(ES_SHADOW_IMPORTANCE);
        //sicb->updateIPVMatrix();

        // Used to cull glowing items & lights
        const core::aabbox3df cambox = camnode->getViewFrustum()->getBoundingBox();

        PROFILER_PUSH_CPU_MARKER("- Shadow", 0x30, 0x6F, 0x90);
        // Shadows
        if (!m_mipviz && !m_wireframe && UserConfigParams::m_shadows)
           //&& World::getWorld()->getTrack()->hasShadows())
        {
            renderShadows(camnode, camera);
        }
        PROFILER_POP_CPU_MARKER();

        PROFILER_PUSH_CPU_MARKER("- Light", 0x00, 0xFF, 0x00);

        // Lights
        renderLights(cambox, camnode, overridemat, cam, dt);
		PROFILER_POP_CPU_MARKER();

		PROFILER_PUSH_CPU_MARKER("- Solid Pass 2", 0x00, 0x00, 0xFF);
        irr_driver->setPhase(SOLID_LIT_PASS);
		glEnable(GL_DEPTH_TEST);
		glDisable(GL_ALPHA_TEST);
		glDepthMask(GL_FALSE);
		glDisable(GL_BLEND);
        m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_SOLID;
        m_scene_manager->drawAll(m_renderpass);

        PROFILER_POP_CPU_MARKER();

		  if (World::getWorld()->getTrack()->isFogEnabled())
		  {
			  PROFILER_PUSH_CPU_MARKER("- Fog", 0xFF, 0x00, 0x00);
			  m_post_processing->renderFog(irr_driver->getInvProjMatrix());
			  PROFILER_POP_CPU_MARKER();
		  }

        PROFILER_PUSH_CPU_MARKER("- Glow", 0xFF, 0xFF, 0x00);

		// Render anything glowing.
		if (!m_mipviz && !m_wireframe)
		{
			irr_driver->setPhase(GLOW_PASS);
			renderGlow(overridemat, glows, cambox, cam);
		} // end glow

        PROFILER_POP_CPU_MARKER();

		PROFILER_PUSH_CPU_MARKER("- Skybox", 0xFF, 0x00, 0xFF);
		renderSkybox();
		PROFILER_POP_CPU_MARKER();

        PROFILER_PUSH_CPU_MARKER("- Lensflare/godray", 0x00, 0xFF, 0xFF);
        // Is the lens flare enabled & visible? Check last frame's query.
        const bool hasflare = World::getWorld()->getTrack()->hasLensFlare();
        const bool hasgodrays = World::getWorld()->getTrack()->hasGodRays();
        if (true)//hasflare || hasgodrays)
        {
            irr::video::COpenGLDriver*	gl_driver = (irr::video::COpenGLDriver*)m_device->getVideoDriver();

            GLuint res = 0;
            if (m_query_issued)
                gl_driver->extGlGetQueryObjectuiv(m_lensflare_query, GL_QUERY_RESULT, &res);
            m_post_processing->setSunPixels(res);

            // Prepare the query for the next frame.
            glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
            gl_driver->extGlBeginQuery(GL_SAMPLES_PASSED_ARB, m_lensflare_query);
            m_scene_manager->setCurrentRendertime(scene::ESNRP_SOLID);
            m_scene_manager->drawAll(scene::ESNRP_CAMERA);
            irr_driver->setPhase(GLOW_PASS);
            m_sun_interposer->render();
            gl_driver->extGlEndQuery(GL_SAMPLES_PASSED_ARB);
            m_query_issued = true;

            m_lensflare->setStrength(res / 4000.0f);

            if (hasflare)
                m_lensflare->OnRegisterSceneNode();

            // Make sure the color mask is reset
            glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        }
        PROFILER_POP_CPU_MARKER();

        // We need to re-render camera due to the per-cam-node hack.
        PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00);
		irr_driver->setPhase(TRANSPARENT_PASS);
		m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_TRANSPARENT;
		glEnable(GL_DEPTH_TEST);
		glDisable(GL_ALPHA_TEST);
		glDepthMask(GL_FALSE);
		glEnable(GL_BLEND);
		glBlendEquation(GL_FUNC_ADD);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glDisable(GL_CULL_FACE);
        m_scene_manager->drawAll(m_renderpass);
		PROFILER_POP_CPU_MARKER();

		PROFILER_PUSH_CPU_MARKER("- Particles", 0xFF, 0xFF, 0x00);
		m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_TRANSPARENT_EFFECT;
		glDepthMask(GL_FALSE);
		glDisable(GL_CULL_FACE);
		glEnable(GL_BLEND);
		glBlendEquation(GL_FUNC_ADD);
		m_scene_manager->drawAll(m_renderpass);
		PROFILER_POP_CPU_MARKER();

        PROFILER_PUSH_CPU_MARKER("- Displacement", 0x00, 0x00, 0xFF);
        // Handle displacing nodes, if any
        const u32 displacingcount = m_displacing.size();
        if (displacingcount)
        {
            renderDisplacement(overridemat, cam);
        }
        PROFILER_POP_CPU_MARKER();

        // Drawing for this cam done, cleanup
        const u32 glowrepcount = transparent_glow_nodes.size();
        for (i = 0; i < glowrepcount; i++)
        {
            transparent_glow_nodes[i]->remove();
            transparent_glow_nodes[i]->drop();
        }

        PROFILER_POP_CPU_MARKER();

        // Note that drawAll must be called before rendering
        // the bullet debug view, since otherwise the camera
        // is not set up properly. This is only used for
        // the bullet debug view.
        if (UserConfigParams::m_artist_debug_mode)
            World::getWorld()->getPhysics()->draw();
    }   // for i<world->getNumKarts()

    PROFILER_PUSH_CPU_MARKER("Postprocessing", 0xFF, 0xFF, 0x00);
    // Render the post-processed scene
    m_post_processing->render();
    PROFILER_POP_CPU_MARKER();

    // Set the viewport back to the full screen for race gui
    m_video_driver->setViewPort(core::recti(0, 0,
                                            UserConfigParams::m_width,
                                            UserConfigParams::m_height));

    for(unsigned int i=0; i<Camera::getNumCameras(); i++)
    {
        Camera *camera = Camera::getCamera(i);
        char marker_name[100];
        sprintf(marker_name, "renderPlayerView() for kart %d", i);

        PROFILER_PUSH_CPU_MARKER(marker_name, 0x00, 0x00, (i+1)*60);
        rg->renderPlayerView(camera, dt);

        PROFILER_POP_CPU_MARKER();
    }  // for i<getNumKarts

    PROFILER_PUSH_CPU_MARKER("GUIEngine", 0x75, 0x75, 0x75);
    // Either render the gui, or the global elements of the race gui.
    GUIEngine::render(dt);
    PROFILER_POP_CPU_MARKER();

    // Render the profiler
    if(UserConfigParams::m_profiler_enabled)
    {
        PROFILER_DRAW();
    }


#ifdef DEBUG
    drawDebugMeshes();
#endif

    PROFILER_PUSH_CPU_MARKER("EndSccene", 0x45, 0x75, 0x45);
    m_video_driver->endScene();
    PROFILER_POP_CPU_MARKER();

    getPostProcessing()->update(dt);
}
Пример #19
0
//-----------------------------------------------------------------------------
/// Draw the markers
void Profiler::draw()
{
    PROFILER_PUSH_CPU_MARKER("ProfilerDraw", 0xFF, 0xFF, 0x00);
    video::IVideoDriver*    driver = irr_driver->getVideoDriver();
    std::stack<Marker>      hovered_markers;

    drawBackground();

    // Force to show the pointer
    irr_driver->showPointer();

    int read_id = !m_write_id;

    // Compute some values for drawing (unit: pixels, but we keep floats for reducing errors accumulation)
    core::dimension2d<u32>    screen_size    = driver->getScreenSize();
    const double profiler_width = (1.0 - 2.0*MARGIN_X) * screen_size.Width;
    const double x_offset    = MARGIN_X*screen_size.Width;
    const double y_offset    = (MARGIN_Y + LINE_HEIGHT)*screen_size.Height;
    const double line_height = LINE_HEIGHT*screen_size.Height;

    size_t nb_thread_infos = m_thread_infos.size();


    double start = -1.0f;
    double end = -1.0f;
    for (size_t i = 0; i < nb_thread_infos; i++)
    {
        MarkerList& markers = m_thread_infos[i].markers_done[read_id];

        MarkerList::const_iterator it_end = markers.end();
        for (MarkerList::const_iterator it = markers.begin(); it != it_end; it++)
        {
            const Marker& m = *it;

            if (start < 0.0) start = m.start;
            else start = std::min(start, m.start);

            if (end < 0.0) end = m.end;
            else end = std::max(end, m.end);
        }
    }
    
    const double duration = end - start;
    const double factor = profiler_width / duration;

    // Get the mouse pos
    core::vector2di mouse_pos = GUIEngine::EventHandler::get()->getMousePos();

    // For each thread:
    for (size_t i = 0; i < nb_thread_infos; i++)
    {
        // Draw all markers
        MarkerList& markers = m_thread_infos[i].markers_done[read_id];

        if (markers.empty())
            continue;

        if (m_capture_report)
        {
            if (m_first_capture_sweep)
                m_capture_report_buffer->getStdStream() << "\"Thread\";";
            else
                m_capture_report_buffer->getStdStream() << i << ";";
        }
        MarkerList::const_iterator it_end = markers.end();
        for (MarkerList::const_iterator it = markers.begin(); it != it_end; it++)
        {
            const Marker&    m = *it;
            assert(m.end >= 0.0);

            if (m_capture_report)
            {
                if (m_first_capture_sweep)
                    m_capture_report_buffer->getStdStream() << "\"" << m.name << "\";";
                else
                    m_capture_report_buffer->getStdStream() << (int)round((m.end - m.start) * 1000) << ";";
            }
            core::rect<s32>    pos((s32)( x_offset + factor*m.start ),
                                   (s32)( y_offset + i*line_height ),
                                   (s32)( x_offset + factor*m.end ),
                                   (s32)( y_offset + (i+1)*line_height ));

            // Reduce vertically the size of the markers according to their layer
            pos.UpperLeftCorner.Y  += m.layer*2;
            pos.LowerRightCorner.Y -= m.layer*2;

            GL32_draw2DRectangle(m.color, pos);

            // If the mouse cursor is over the marker, get its information
            if(pos.isPointInside(mouse_pos))
                hovered_markers.push(m);
        }

        if (m_capture_report)
        {
            m_capture_report_buffer->getStdStream() << "\n";
            m_first_capture_sweep = false;
        }
    }
    
    // GPU profiler
    QueryPerf hovered_gpu_marker = Q_LAST;
    long hovered_gpu_marker_elapsed = 0;
    int gpu_y = int(y_offset + nb_thread_infos*line_height + line_height/2);
    float total = 0;
    unsigned int gpu_timers[Q_LAST];
    for (unsigned i = 0; i < Q_LAST; i++)
    {
        gpu_timers[i] = irr_driver->getGPUTimer(i).elapsedTimeus();
        total += gpu_timers[i];
    }
    
    static video::SColor colors[] = {
        video::SColor(255, 255, 0, 0),
        video::SColor(255, 0, 255, 0),
        video::SColor(255, 0, 0, 255),
        video::SColor(255, 255, 255, 0),
        video::SColor(255, 255, 0, 255),
        video::SColor(255, 0, 255, 255)
    };

    if (hovered_markers.size() == 0)
    {
        float curr_val = 0;
        for (unsigned i = 0; i < Q_LAST; i++)
        {
            //Log::info("GPU Perf", "Phase %d : %d us\n", i, irr_driver->getGPUTimer(i).elapsedTimeus());

            float elapsed = float(gpu_timers[i]);
            core::rect<s32> pos((s32)(x_offset + (curr_val / total)*profiler_width),
                (s32)(y_offset + gpu_y),
                (s32)(x_offset + ((curr_val + elapsed) / total)*profiler_width),
                (s32)(y_offset + gpu_y + line_height));

            curr_val += elapsed;
            GL32_draw2DRectangle(colors[i % 6], pos);

            if (pos.isPointInside(mouse_pos))
            {
                hovered_gpu_marker = (QueryPerf)i;
                hovered_gpu_marker_elapsed = gpu_timers[i];
            }

            if (m_capture_report)
            {
                if (m_first_gpu_capture_sweep)
                    m_gpu_capture_report_buffer->getStdStream() << GPU_Phase[i] << ";";
                else
                    m_gpu_capture_report_buffer->getStdStream() << elapsed << ";";
            }
        }

        if (m_capture_report)
        {
            m_gpu_capture_report_buffer->getStdStream() << "\n";
            m_first_gpu_capture_sweep = false;
        }
    }

    // Draw the end of the frame
    {
        s32 x_sync = (s32)(x_offset + factor*m_time_between_sync);
        s32 y_up_sync = (s32)(MARGIN_Y*screen_size.Height);
        s32 y_down_sync = (s32)( (MARGIN_Y + (2+nb_thread_infos)*LINE_HEIGHT)*screen_size.Height );

        driver->draw2DLine(core::vector2di(x_sync, y_up_sync),
                           core::vector2di(x_sync, y_down_sync),
                           video::SColor(0xFF, 0x00, 0x00, 0x00));
    }

    // Draw the hovered markers' names
    gui::ScalableFont* font = GUIEngine::getFont();
    if (font)
    {
        core::stringw text;
        while(!hovered_markers.empty())
        {
            Marker& m = hovered_markers.top();
            std::ostringstream oss;
            oss.precision(4);
            oss << m.name << " [" << (m.end - m.start) << " ms / ";
            oss.precision(3);
            oss << (m.end - m.start)*100.0 / duration << "%]" << std::endl;
            text += oss.str().c_str();
            hovered_markers.pop();
        }
        font->draw(text, MARKERS_NAMES_POS, video::SColor(0xFF, 0xFF, 0x00, 0x00));

        if (hovered_gpu_marker != Q_LAST)
        {
            std::ostringstream oss;
            oss << GPU_Phase[hovered_gpu_marker] << " : " << hovered_gpu_marker_elapsed << " us";
            font->draw(oss.str().c_str(), GPU_MARKERS_NAMES_POS, video::SColor(0xFF, 0xFF, 0x00, 0x00));
        }
    }

    if (m_capture_report)
    {
        font->draw("Capturing profiler report...", MARKERS_NAMES_POS, video::SColor(0xFF, 0x00, 0x90, 0x00));
    }

    PROFILER_POP_CPU_MARKER();
}
Пример #20
0
void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned pointlightcount, std::vector<GlowData>& glows, float dt, bool hasShadow, bool forceRTT)
{
    glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedObject::ViewProjectionMatrixesUBO);
    m_scene_manager->setActiveCamera(camnode);

    PROFILER_PUSH_CPU_MARKER("- Draw Call Generation", 0xFF, 0xFF, 0xFF);
    PrepareDrawCalls(camnode);
    PROFILER_POP_CPU_MARKER();
    // Shadows
    {
        // To avoid wrong culling, use the largest view possible
        m_scene_manager->setActiveCamera(m_suncam);
        if (!m_mipviz && !m_wireframe && UserConfigParams::m_dynamic_lights &&
            UserConfigParams::m_shadows && !irr_driver->needUBOWorkaround() && hasShadow)
        {
            PROFILER_PUSH_CPU_MARKER("- Shadow", 0x30, 0x6F, 0x90);
            renderShadows();
            PROFILER_POP_CPU_MARKER();
            if (UserConfigParams::m_gi)
            {
                PROFILER_PUSH_CPU_MARKER("- RSM", 0xFF, 0x0, 0xFF);
                renderRSM();
                PROFILER_POP_CPU_MARKER();
            }
        }
        m_scene_manager->setActiveCamera(camnode);

    }

    PROFILER_PUSH_CPU_MARKER("- Solid Pass 1", 0xFF, 0x00, 0x00);
    glDepthMask(GL_TRUE);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);
    glEnable(GL_CULL_FACE);
    if (UserConfigParams::m_dynamic_lights || forceRTT)
    {
        m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).Bind();
        glClearColor(0., 0., 0., 0.);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        renderSolidFirstPass();
    }
    PROFILER_POP_CPU_MARKER();



    // Lights
    {
        PROFILER_PUSH_CPU_MARKER("- Light", 0x00, 0xFF, 0x00);
        if (UserConfigParams::m_dynamic_lights)
            renderLights(pointlightcount, hasShadow);
        PROFILER_POP_CPU_MARKER();
    }

    // Handle SSAO
    {
        PROFILER_PUSH_CPU_MARKER("- SSAO", 0xFF, 0xFF, 0x00);
        ScopedGPUTimer Timer(getGPUTimer(Q_SSAO));
        if (UserConfigParams::m_ssao)
            renderSSAO();
        PROFILER_POP_CPU_MARKER();
    }

    PROFILER_PUSH_CPU_MARKER("- Solid Pass 2", 0x00, 0x00, 0xFF);
    if (UserConfigParams::m_dynamic_lights || forceRTT)
    {
        m_rtts->getFBO(FBO_COLORS).Bind();
        SColor clearColor(0, 150, 150, 150);
        if (World::getWorld() != NULL)
            clearColor = World::getWorld()->getClearColor();

        glClearColor(clearColor.getRed() / 255.f, clearColor.getGreen() / 255.f,
            clearColor.getBlue() / 255.f, clearColor.getAlpha() / 255.f);
        glClear(GL_COLOR_BUFFER_BIT);
        glDepthMask(GL_FALSE);
    }
    renderSolidSecondPass();
    PROFILER_POP_CPU_MARKER();

    if (getNormals())
    {
        m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).Bind();
        renderNormalsVisualisation();
        m_rtts->getFBO(FBO_COLORS).Bind();
    }

    if (UserConfigParams::m_dynamic_lights && World::getWorld() != NULL &&
        World::getWorld()->isFogEnabled())
    {
        PROFILER_PUSH_CPU_MARKER("- Fog", 0xFF, 0x00, 0x00);
        m_post_processing->renderFog();
        PROFILER_POP_CPU_MARKER();
    }

    PROFILER_PUSH_CPU_MARKER("- Skybox", 0xFF, 0x00, 0xFF);
    renderSkybox(camnode);
    PROFILER_POP_CPU_MARKER();

    if (getRH())
    {
        m_rtts->getFBO(FBO_COLORS).Bind();
        m_post_processing->renderRHDebug(m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2], rh_matrix, rh_extend);
    }

    if (getGI())
    {
        m_rtts->getFBO(FBO_COLORS).Bind();
        m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]);
    }

    PROFILER_PUSH_CPU_MARKER("- Glow", 0xFF, 0xFF, 0x00);
    // Render anything glowing.
    if (!m_mipviz && !m_wireframe && UserConfigParams::m_glow)
    {
        irr_driver->setPhase(GLOW_PASS);
        renderGlow(glows);
    } // end glow
    PROFILER_POP_CPU_MARKER();

    PROFILER_PUSH_CPU_MARKER("- Lensflare/godray", 0x00, 0xFF, 0xFF);
    computeSunVisibility();
    PROFILER_POP_CPU_MARKER();

    // Render transparent
    {
        PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(getGPUTimer(Q_TRANSPARENT));
        renderTransparent();
        PROFILER_POP_CPU_MARKER();
    }

    m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);

    // Render particles
    {
        PROFILER_PUSH_CPU_MARKER("- Particles", 0xFF, 0xFF, 0x00);
        ScopedGPUTimer Timer(getGPUTimer(Q_PARTICLES));
        renderParticles();
        PROFILER_POP_CPU_MARKER();
    }
    if (!UserConfigParams::m_dynamic_lights && !forceRTT)
    {
        glDisable(GL_FRAMEBUFFER_SRGB);
        glDisable(GL_DEPTH_TEST);
        glDepthMask(GL_FALSE);
        return;
    }

    // Ensure that no object will be drawn after that by using invalid pass
    irr_driver->setPhase(PASS_COUNT);
}
Пример #21
0
/** Updates the physics, all karts, the track, and projectile manager.
 *  \param dt Time step size.
 */
void World::update(float dt)
{
#ifdef DEBUG
    assert(m_magic_number == 0xB01D6543);
#endif

    PROFILER_PUSH_CPU_MARKER("World::update()", 0x00, 0x7F, 0x00);

#if MEASURE_FPS
    static float time = 0.0f;
    time += dt;
    if (time > 5.0f)
    {
        time -= 5.0f;
        printf("%i\n",irr_driver->getVideoDriver()->getFPS());
    }
#endif

    PROFILER_PUSH_CPU_MARKER("World::update (sub-updates)", 0x20, 0x7F, 0x00);
    WorldStatus::update(dt);
    RewindManager::get()->saveStates();
    PROFILER_POP_CPU_MARKER();

    PROFILER_PUSH_CPU_MARKER("World::update (Kart::upate)", 0x40, 0x7F, 0x00);

    // Update all the karts. This in turn will also update the controller,
    // which causes all AI steering commands set. So in the following 
    // physics update the new steering is taken into account.
    const int kart_amount = (int)m_karts.size();
    for (int i = 0 ; i < kart_amount; ++i)
    {
        SpareTireAI* sta =
            dynamic_cast<SpareTireAI*>(m_karts[i]->getController());
        // Update all karts that are not eliminated
        if(!m_karts[i]->isEliminated() || (sta && sta->isMoving()))
            m_karts[i]->update(dt);
    }
    PROFILER_POP_CPU_MARKER();

    PROFILER_PUSH_CPU_MARKER("World::update (camera)", 0x60, 0x7F, 0x00);
    for(unsigned int i=0; i<Camera::getNumCameras(); i++)
    {
        Camera::getCamera(i)->update(dt);
    }
    PROFILER_POP_CPU_MARKER();

    if(race_manager->isRecordingRace()) ReplayRecorder::get()->update(dt);
    Scripting::ScriptEngine *script_engine = Scripting::ScriptEngine::getInstance();
    if (script_engine) script_engine->update(dt);

    if (!history->dontDoPhysics())
    {
        Physics::getInstance()->update(dt);
    }

    PROFILER_PUSH_CPU_MARKER("World::update (weather)", 0x80, 0x7F, 0x00);
    if (UserConfigParams::m_graphical_effects && Weather::getInstance())
    {
        Weather::getInstance()->update(dt);
    }
    PROFILER_POP_CPU_MARKER();

    PROFILER_PUSH_CPU_MARKER("World::update (projectiles)", 0xa0, 0x7F, 0x00);
    projectile_manager->update(dt);
    PROFILER_POP_CPU_MARKER();

    PROFILER_POP_CPU_MARKER();

#ifdef DEBUG
    assert(m_magic_number == 0xB01D6543);
#endif
}   // update
Пример #22
0
/** Run the actual main loop.
 */
void MainLoop::run()
{
    IrrlichtDevice* device = irr_driver->getDevice();

    m_curr_time = device->getTimer()->getRealTime();
    while(!m_abort)
    {
        PROFILER_PUSH_CPU_MARKER("Main loop", 0xFF, 0x00, 0xF7);

        m_prev_time = m_curr_time;
        float dt   = getLimitedDt();

        if (World::getWorld())  // race is active if world exists
        {
            PROFILER_PUSH_CPU_MARKER("Update race", 0, 255, 255);
            updateRace(dt);
            PROFILER_POP_CPU_MARKER();
        }   // if race is active

        // We need to check again because update_race may have requested
        // the main loop to abort; and it's not a good idea to continue
        // since the GUI engine is no more to be called then.
        // Also only do music, input, and graphics update if graphics are
        // enabled.
        if (!m_abort && !ProfileWorld::isNoGraphics())
        {
            PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00);
            music_manager->update(dt);

            input_manager->update(dt);

            #ifdef ENABLE_WIIUSE
                wiimote_manager->update();
            #endif
            
            GUIEngine::update(dt);
            PROFILER_POP_CPU_MARKER();

            PROFILER_PUSH_CPU_MARKER("IrrDriver update", 0x00, 0x00, 0x7F);
            irr_driver->update(dt);
            PROFILER_POP_CPU_MARKER();

            PROFILER_PUSH_CPU_MARKER("Protocol manager update", 0x7F, 0x00, 0x7F);
            ProtocolManager::getInstance()->update();
            PROFILER_POP_CPU_MARKER();

            PROFILER_PUSH_CPU_MARKER("Database polling update", 0x00, 0x7F, 0x7F);
            Online::RequestManager::get()->update(dt);
            PROFILER_POP_CPU_MARKER();

            PROFILER_SYNC_FRAME();
        }
        else if (!m_abort && ProfileWorld::isNoGraphics())
        {
            PROFILER_PUSH_CPU_MARKER("Protocol manager update", 0x7F, 0x00, 0x7F);
            ProtocolManager::getInstance()->update();
            PROFILER_POP_CPU_MARKER();

            PROFILER_PUSH_CPU_MARKER("Database polling update", 0x00, 0x7F, 0x7F);
            Online::RequestManager::get()->update(dt);
            PROFILER_POP_CPU_MARKER();
        }

        PROFILER_SYNC_FRAME();
        PROFILER_POP_CPU_MARKER();
    }  // while !m_exit

}   // run
Пример #23
0
/** Updates the physics simulation and handles all collisions.
 *  \param ticks Number of physics steps to simulate.
 */
void Physics::update(int ticks)
{
    PROFILER_PUSH_CPU_MARKER("Physics", 0, 0, 0);

    m_physics_loop_active = true;
    // Bullet can report the same collision more than once (up to 4
    // contact points per collision). Additionally, more than one internal
    // substep might be taken, resulting in potentially even more
    // duplicates. To handle this, all collisions (i.e. pair of objects)
    // are stored in a vector, but only one entry per collision pair
    // of objects.
    m_all_collisions.clear();

    // Since the world update (which calls physics update) is called at the
    // fixed frequency necessary for the physics update, we need to do exactly
    // one physic step only.
    double start;
    if(UserConfigParams::m_physics_debug) start = StkTime::getRealTime();

    m_dynamics_world->stepSimulation(stk_config->ticks2Time(1), 1,
                                     stk_config->ticks2Time(1)      );
    if (UserConfigParams::m_physics_debug)
    {
        Log::verbose("Physics", "At %d physics duration %12.8f",
                     World::getWorld()->getTicksSinceStart(),
                     StkTime::getRealTime() - start);
    }

    // Now handle the actual collision. Note: flyables can not be removed
    // inside of this loop, since the same flyables might hit more than one
    // other object. So only a flag is set in the flyables, the actual
    // clean up is then done later in the projectile manager.
    std::vector<CollisionPair>::iterator p;
    for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p)
    {
        // Kart-kart collision
        // --------------------
        if(p->getUserPointer(0)->is(UserPointer::UP_KART))
        {
            KartKartCollision(p->getUserPointer(0)->getPointerKart(),
                              p->getContactPointCS(0),
                              p->getUserPointer(1)->getPointerKart(),
                              p->getContactPointCS(1)                );
            Scripting::ScriptEngine* script_engine =
                                            Scripting::ScriptEngine::getInstance();
            int kartid1 = p->getUserPointer(0)->getPointerKart()->getWorldKartId();
            int kartid2 = p->getUserPointer(1)->getPointerKart()->getWorldKartId();
            script_engine->runFunction(false, "void onKartKartCollision(int, int)",
                [=](asIScriptContext* ctx) {
                    ctx->SetArgDWord(0, kartid1);
                    ctx->SetArgDWord(1, kartid2);
                });
            continue;
        }  // if kart-kart collision

        if(p->getUserPointer(0)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Kart hits physical object
            // -------------------------
            Scripting::ScriptEngine* script_engine = Scripting::ScriptEngine::getInstance();
            AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
            int kartId = kart->getWorldKartId();
            PhysicalObject* obj = p->getUserPointer(0)->getPointerPhysicalObject();
            std::string obj_id = obj->getID();
            std::string scripting_function = obj->getOnKartCollisionFunction();

            TrackObject* to = obj->getTrackObject();
            TrackObject* library = to->getParentLibrary();
            std::string lib_id;
            std::string* lib_id_ptr = NULL;
            if (library != NULL)
                lib_id = library->getID();
            lib_id_ptr = &lib_id;

            if (scripting_function.size() > 0)
            {
                script_engine->runFunction(true, "void " + scripting_function + "(int, const string, const string)",
                    [&](asIScriptContext* ctx) {
                        ctx->SetArgDWord(0, kartId);
                        ctx->SetArgObject(1, lib_id_ptr);
                        ctx->SetArgObject(2, &obj_id);
                    });
            }
            if (obj->isCrashReset())
            {
                new RescueAnimation(kart);
            }
            else if (obj->isExplodeKartObject())
            {
                ExplosionAnimation::create(kart);
                if (kart->getKartAnimation() != NULL)
                {
                    World::getWorld()->kartHit(kart->getWorldKartId());
                }
            }
            else if (obj->isFlattenKartObject())
            {
                const KartProperties *kp = kart->getKartProperties();
                // Count squash only once from original state
                bool was_squashed = kart->isSquashed();
                if (kart->setSquash(kp->getSwatterSquashDuration(),
                    kp->getSwatterSquashSlowdown()) && !was_squashed)
                {
                    World::getWorld()->kartHit(kart->getWorldKartId());
                }
            }
            else if(obj->isSoccerBall() && 
                    race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
            {
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setBallHitter(kartId);
            }
            continue;
        }

        if (p->getUserPointer(0)->is(UserPointer::UP_ANIMATION))
        {
            // Kart hits animation
            ThreeDAnimation *anim=p->getUserPointer(0)->getPointerAnimation();
            if(anim->isCrashReset())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                new RescueAnimation(kart);
            }
            else if (anim->isExplodeKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                ExplosionAnimation::create(kart);
                if (kart->getKartAnimation() != NULL)
                {
                    World::getWorld()->kartHit(kart->getWorldKartId());
                }
            }
            else if (anim->isFlattenKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                const KartProperties *kp = kart->getKartProperties();

                // Count squash only once from original state
                bool was_squashed = kart->isSquashed();
                if (kart->setSquash(kp->getSwatterSquashDuration(),
                    kp->getSwatterSquashSlowdown()) && !was_squashed)
                {
                    World::getWorld()->kartHit(kart->getWorldKartId());
                }

            }
            continue;

        }
        // now the first object must be a projectile
        // =========================================
        if(p->getUserPointer(1)->is(UserPointer::UP_TRACK))
        {
            // Projectile hits track
            // ---------------------
            p->getUserPointer(0)->getPointerFlyable()->hitTrack();
        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Projectile hits physical object
            // -------------------------------
            Scripting::ScriptEngine* script_engine = Scripting::ScriptEngine::getInstance();
            Flyable* flyable = p->getUserPointer(0)->getPointerFlyable();
            PhysicalObject* obj = p->getUserPointer(1)->getPointerPhysicalObject();
            std::string obj_id = obj->getID();
            std::string scripting_function = obj->getOnItemCollisionFunction();
            if (scripting_function.size() > 0)
            {
                script_engine->runFunction(true, "void " + scripting_function + "(int, int, const string)",
                        [&](asIScriptContext* ctx) {
                        ctx->SetArgDWord(0, (int)flyable->getType());
                        ctx->SetArgDWord(1, flyable->getOwnerId());
                        ctx->SetArgObject(2, &obj_id);
                    });
            }
            flyable->hit(NULL, obj);

            if (obj->isSoccerBall() && 
                race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
            {
                int kartId = p->getUserPointer(0)->getPointerFlyable()->getOwnerId();
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setBallHitter(kartId);
            }

        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_KART))
        {
            // Projectile hits kart
            // --------------------
            // Only explode a bowling ball if the target is
            // not invulnerable
            AbstractKart* target_kart = p->getUserPointer(1)->getPointerKart();
            PowerupManager::PowerupType type = p->getUserPointer(0)->getPointerFlyable()->getType();
            if(type != PowerupManager::POWERUP_BOWLING || !target_kart->isInvulnerable())
            {
                Flyable *f = p->getUserPointer(0)->getPointerFlyable();
                f->hit(target_kart);

                // Check for achievements
                AbstractKart * kart = World::getWorld()->getKart(f->getOwnerId());
                LocalPlayerController *lpc =
                    dynamic_cast<LocalPlayerController*>(kart->getController());

                // Check that it's not a kart hitting itself (this can
                // happen at the time a flyable is shot - release too close
                // to the kart, and it's the current player. At this stage
                // only the current player can get achievements.
                if (target_kart != kart && lpc && lpc->canGetAchievements())
                {
                    if (type == PowerupManager::POWERUP_BOWLING)
                    {
                        PlayerManager::increaseAchievement(AchievementsStatus::BOWLING_HIT, 1);
                        if (race_manager->isLinearRaceMode())
                            PlayerManager::increaseAchievement(AchievementsStatus::BOWLING_HIT_1RACE, 1);
                    }   // is bowling ball
                }   // if target_kart != kart && is a player kart and is current player
            }

        }
        else
        {
            // Projectile hits projectile
            // --------------------------
            p->getUserPointer(0)->getPointerFlyable()->hit(NULL);
            p->getUserPointer(1)->getPointerFlyable()->hit(NULL);
        }
    }  // for all p in m_all_collisions

    m_physics_loop_active = false;
    // Now remove the karts that were removed while the above loop
    // was active. Now we can safely call removeKart, since the loop
    // is finished and m_physics_world_active is not set anymore.
    for(unsigned int i=0; i<m_karts_to_delete.size(); i++)
        removeKart(m_karts_to_delete[i]);
    m_karts_to_delete.clear();

    PROFILER_POP_CPU_MARKER();
}   // update
Пример #24
0
/** Updates the physics, all karts, the track, and projectile manager.
 *  \param dt Time step size.
 */
void World::update(float dt)
{
#ifdef DEBUG
    assert(m_magic_number == 0xB01D6543);
#endif


    PROFILER_PUSH_CPU_MARKER("World::update()", 0x00, 0x7F, 0x00);

#if MEASURE_FPS
    static float time = 0.0f;
    time += dt;
    if (time > 5.0f)
    {
        time -= 5.0f;
        printf("%i\n",irr_driver->getVideoDriver()->getFPS());
    }
#endif

    PROFILER_PUSH_CPU_MARKER("World::update (sub-updates)", 0x20, 0x7F, 0x00);
    history->update(dt);
    if(ReplayRecorder::get()) ReplayRecorder::get()->update(dt);
    if(ReplayPlay::get()) ReplayPlay::get()->update(dt);
    if(history->replayHistory()) dt=history->getNextDelta();
    WorldStatus::update(dt);
    if (m_script_engine) m_script_engine->update(dt);
    PROFILER_POP_CPU_MARKER();

    if (!history->dontDoPhysics())
    {
        m_physics->update(dt);
    }

    PROFILER_PUSH_CPU_MARKER("World::update (Kart::upate)", 0x40, 0x7F, 0x00);
    const int kart_amount = (int)m_karts.size();
    for (int i = 0 ; i < kart_amount; ++i)
    {
        // Update all karts that are not eliminated
        if(!m_karts[i]->isEliminated()) m_karts[i]->update(dt) ;
    }
    PROFILER_POP_CPU_MARKER();

    PROFILER_PUSH_CPU_MARKER("World::update (camera)", 0x60, 0x7F, 0x00);
    for(unsigned int i=0; i<Camera::getNumCameras(); i++)
    {
        Camera::getCamera(i)->update(dt);
    }
    PROFILER_POP_CPU_MARKER();

    PROFILER_PUSH_CPU_MARKER("World::update (weather)", 0x80, 0x7F, 0x00);
    if (UserConfigParams::m_graphical_effects && m_weather)
    {
        m_weather->update(dt);
    }
    PROFILER_POP_CPU_MARKER();

    PROFILER_PUSH_CPU_MARKER("World::update (projectiles)", 0xa0, 0x7F, 0x00);
    projectile_manager->update(dt);
    PROFILER_POP_CPU_MARKER();

    PROFILER_POP_CPU_MARKER();

#ifdef DEBUG
    assert(m_magic_number == 0xB01D6543);
#endif
}   // update
Пример #25
0
/** Updates the physics simulation and handles all collisions.
 *  \param dt Time step.
 */
void Physics::update(float dt)
{
    PROFILER_PUSH_CPU_MARKER("Physics", 0, 0, 0);

    m_physics_loop_active = true;
    // Bullet can report the same collision more than once (up to 4
    // contact points per collision). Additionally, more than one internal
    // substep might be taken, resulting in potentially even more
    // duplicates. To handle this, all collisions (i.e. pair of objects)
    // are stored in a vector, but only one entry per collision pair
    // of objects.
    m_all_collisions.clear();

    // Maximum of three substeps. This will work for framerate down to
    // 20 FPS (bullet default frequency is 60 HZ).
    m_dynamics_world->stepSimulation(dt, 3);

    // Now handle the actual collision. Note: flyables can not be removed
    // inside of this loop, since the same flyables might hit more than one
    // other object. So only a flag is set in the flyables, the actual
    // clean up is then done later in the projectile manager.
    std::vector<CollisionPair>::iterator p;
    for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p)
    {
        // Kart-kart collision
        // --------------------
        if(p->getUserPointer(0)->is(UserPointer::UP_KART))
        {
            KartKartCollision(p->getUserPointer(0)->getPointerKart(),
                              p->getContactPointCS(0),
                              p->getUserPointer(1)->getPointerKart(),
                              p->getContactPointCS(1)                );
            continue;
        }  // if kart-kart collision

        if(p->getUserPointer(0)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Kart hits physical object
            // -------------------------
            PhysicalObject *obj = p->getUserPointer(0)
                                   ->getPointerPhysicalObject();
            if(obj->isCrashReset())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                new RescueAnimation(kart);
            }
            else if (obj->isExplodeKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                ExplosionAnimation::create(kart);
            }
            else if (obj->isFlattenKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                const KartProperties* kp = kart->getKartProperties();
                kart->setSquash(kp->getSquashDuration(), kp->getSquashSlowdown());
            }
            else if(obj->isSoccerBall())
            {
                int kartId = p->getUserPointer(1)->getPointerKart()->getWorldKartId();
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setLastKartTohitBall(kartId);
            }
            continue;
        }

        if(p->getUserPointer(0)->is(UserPointer::UP_ANIMATION))
        {
            // Kart hits animation
            ThreeDAnimation *anim=p->getUserPointer(0)->getPointerAnimation();
            if(anim->isCrashReset())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                new RescueAnimation(kart);
            }
            else if (anim->isExplodeKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                ExplosionAnimation::create(kart);
            }
            else if (anim->isFlattenKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                const KartProperties* kp = kart->getKartProperties();
                kart->setSquash(kp->getSquashDuration(), kp->getSquashSlowdown());
            }
            continue;

        }
        // now the first object must be a projectile
        // =========================================
        if(p->getUserPointer(1)->is(UserPointer::UP_TRACK))
        {
            // Projectile hits track
            // ---------------------
            p->getUserPointer(0)->getPointerFlyable()->hitTrack();
        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Projectile hits physical object
            // -------------------------------
            p->getUserPointer(0)->getPointerFlyable()
                ->hit(NULL, p->getUserPointer(1)->getPointerPhysicalObject());
            PhysicalObject* obj = p->getUserPointer(1)->getPointerPhysicalObject();
            if(obj->isSoccerBall())
            {
                int kartId = p->getUserPointer(0)->getPointerFlyable()->getOwnerId();
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setLastKartTohitBall(kartId);
            }

        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_KART))
        {
            // Projectile hits kart
            // --------------------
            // Only explode a bowling ball if the target is
            // not invulnerable
            AbstractKart* target_kart = p->getUserPointer(1)->getPointerKart();
            PowerupManager::PowerupType type = p->getUserPointer(0)->getPointerFlyable()->getType();
            if(type != PowerupManager::POWERUP_BOWLING || !target_kart->isInvulnerable())
            {
                p->getUserPointer(0)->getPointerFlyable()->hit(target_kart);
                if ( type ==PowerupManager::POWERUP_BOWLING )
                    ((SingleAchievement *) AchievementsManager::get()->getActive()->getAchievement(2))->increase(1);
            }

        }
        else
        {
            // Projectile hits projectile
            // --------------------------
            p->getUserPointer(0)->getPointerFlyable()->hit(NULL);
            p->getUserPointer(1)->getPointerFlyable()->hit(NULL);
        }
    }  // for all p in m_all_collisions

    m_physics_loop_active = false;
    // Now remove the karts that were removed while the above loop
    // was active. Now we can safely call removeKart, since the loop
    // is finished and m_physics_world_active is not set anymore.
    for(unsigned int i=0; i<m_karts_to_delete.size(); i++)
        removeKart(m_karts_to_delete[i]);
    m_karts_to_delete.clear();

    PROFILER_POP_CPU_MARKER();
}   // update
Пример #26
0
/** Run the actual main loop.
 *  The sequnce in which various parts of STK are updated is:
 *  - Determine next time step size (`getLimitedDt`). This takes maximum fps
 *    into account (i.e. sleep if the fps would be too high), and will actually
 *    slow down the in-game clock if the fps are too low (if more than 3/60 of
 *    a second have passed, more than 3 physics time steps would be needed, 
 *    and physics do at most 3 time steps).
 *  - if a race is taking place (i.e. not only a menu being shown), call
 *    `updateRace()`, which is a thin wrapper around a call to
 *    `World::updateWorld()`:
 *    - Update history manager (which will either set the kart position and/or
 *      controls when replaying, or store the current info for a replay).
 *      This is mostly for debugging only (though available even in release
 *      mode).
 *    - Updates Replays - either storing data when not replaying, or
 *      updating kart positions/control when replaying).
 *    - Calls `WorldStatus::update()`, which updates the race state (e.g.
 *      go from 'ready' to 'set' etc), and clock.
 *    - Updates the physics (`Physics::update()`). This will simulate all
 *      physical objects for the specified time with bullet.
 *    - Updates all karts (`Kart::update()`). Obviously the update function
 *      does a lot more than what is described here, this is only supposed to
 *      be a _very_ high level overview:
 *      - Updates its rewinder (to store potentially changed controls
 *        as events) in `KartRewinder::update()`.
 *      - Calls `Moveable::update()`, which takes the new position from
 *        the physics and saves it (and computes dependent values, like
 *        heading, local velocity).
 *      - Updates its controller. This is either:
 *        - an AI using `SkiddingController::update()` (which then will
 *          compute the new controls), or 
 *        - a player controller using `PlayerController::update()`, which will
 *          handle smooth steering (in case of digital input devices steering
 *          is adjusted a bit over time to avoid an instant change from all
 *          left to all right). Input events will be handled when updating
 *          the irrlicht driver later at the end of the main loop.
 *      - Updates kart animation (like rescue, ...) if one is shown atm.
 *      - Update attachments.
 *      - update physics, i.e. taking the current steering and updating
 *        the bullet raycast vehicle with that data. The settings are actually
 *        only used in the next frame when the physics are updated.
 *    - Updates all cameras via `Camera::update()`. The camera position and
 *      rotation is adjusted according to the position etc of the kart (and
 *      special circumstances like rescue, falling).
 *    - Updates all projectiles using the projectile manager. Some of the
 *      projectiles are mostly handled by the physics (e.g. a cake will mainly
 *      check if it's out of bounds), others (like basket ball) do all 
 *      their aiming and movement here.
 *    - Updates the rewind manager to store rewind states.
 *  - Updates the music manager.
 *  - Updates the input manager (which only updates internal time, actual
 *    input handling follows late)
 *  - Updates the wiimote manager. This will read the data of all wiimotes
 *    and feed the corresponding events to the irrlicht event system.
 *  - Updates the STK internal gui engine. This updates all widgets, and
 *    e.g. takes care of the rotation of the karts in the KartSelection
 *    screen using the ModelViewWidget.
 *  - Updates STK's irrlicht driver `IrrDriver::update()`:
 *    - Calls Irrlicht's `beginScene()` .
 *    - Renders the scene (several times with different viewport if
 *      split screen is being used)
 *    - Calls `GUIEngine::render()`, which renders all widgets with the
 *      help of Irrlicht's GUIEnvironment (`drawAll()`). This will also
 *      handle all events, i.e. all input is now handled (e.g. steering,
 *      firing etc are all set in the corresponding karts depending on
 *      user input).
 *    - Calls Irrlicht's `endScene()`
 */
void MainLoop::run()
{
    IrrlichtDevice* device = irr_driver->getDevice();

    m_curr_time = device->getTimer()->getRealTime();
    while(!m_abort)
    {
        PROFILER_PUSH_CPU_MARKER("Main loop", 0xFF, 0x00, 0xF7);

        m_prev_time = m_curr_time;
        float dt   = getLimitedDt();

        if (!m_abort && !ProfileWorld::isNoGraphics())
        {
            // Render the previous frame, and also handle all user input.
            PROFILER_PUSH_CPU_MARKER("IrrDriver update", 0x00, 0x00, 0x7F);
            irr_driver->update(dt);
            PROFILER_POP_CPU_MARKER();
        }

        if (World::getWorld())  // race is active if world exists
        {
            PROFILER_PUSH_CPU_MARKER("Update race", 0, 255, 255);
            updateRace(dt);
            PROFILER_POP_CPU_MARKER();
        }   // if race is active

        // We need to check again because update_race may have requested
        // the main loop to abort; and it's not a good idea to continue
        // since the GUI engine is no more to be called then.
        // Also only do music, input, and graphics update if graphics are
        // enabled.
        if (!m_abort && !ProfileWorld::isNoGraphics())
        {
            PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00);
            input_manager->update(dt);

            #ifdef ENABLE_WIIUSE
                wiimote_manager->update();
            #endif
            
            GUIEngine::update(dt);
            PROFILER_POP_CPU_MARKER();

            // Update sfx and music after graphics, so that graphics code
            // can use as many threads as possible without interfering
            // with audio
            PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00);
            SFXManager::get()->update();
            PROFILER_POP_CPU_MARKER();

            PROFILER_PUSH_CPU_MARKER("Protocol manager update", 0x7F, 0x00, 0x7F);
            if (STKHost::existHost())
            {
                if (STKHost::get()->requestedShutdown())
                    STKHost::get()->shutdown();
                else
                    ProtocolManager::getInstance()->update(dt);
            }
            PROFILER_POP_CPU_MARKER();

            PROFILER_PUSH_CPU_MARKER("Database polling update", 0x00, 0x7F, 0x7F);
            Online::RequestManager::get()->update(dt);
            PROFILER_POP_CPU_MARKER();
        }
        else if (!m_abort && ProfileWorld::isNoGraphics())
        {
            PROFILER_PUSH_CPU_MARKER("Protocol manager update", 0x7F, 0x00, 0x7F);
            if(NetworkConfig::get()->isNetworking())
                ProtocolManager::getInstance()->update(dt);
            PROFILER_POP_CPU_MARKER();

            PROFILER_PUSH_CPU_MARKER("Database polling update", 0x00, 0x7F, 0x7F);
            Online::RequestManager::get()->update(dt);
            PROFILER_POP_CPU_MARKER();
        }

        if (World::getWorld() )
        {
            World::getWorld()->updateTime(dt);
        }

        PROFILER_POP_CPU_MARKER();
        PROFILER_SYNC_FRAME();
    }  // while !m_abort

}   // run
Пример #27
0
/** Updates the physics simulation and handles all collisions.
 *  \param dt Time step.
 */
void Physics::update(float dt)
{
    PROFILER_PUSH_CPU_MARKER("Physics", 0, 0, 0);

    m_physics_loop_active = true;
    // Bullet can report the same collision more than once (up to 4
    // contact points per collision). Additionally, more than one internal
    // substep might be taken, resulting in potentially even more
    // duplicates. To handle this, all collisions (i.e. pair of objects)
    // are stored in a vector, but only one entry per collision pair
    // of objects.
    m_all_collisions.clear();

    // Maximum of three substeps. This will work for framerate down to
    // 20 FPS (bullet default frequency is 60 HZ).
    m_dynamics_world->stepSimulation(dt, 3);

    // Now handle the actual collision. Note: flyables can not be removed
    // inside of this loop, since the same flyables might hit more than one
    // other object. So only a flag is set in the flyables, the actual
    // clean up is then done later in the projectile manager.
    std::vector<CollisionPair>::iterator p;
    for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p)
    {
        // Kart-kart collision
        // --------------------
        if(p->getUserPointer(0)->is(UserPointer::UP_KART))
        {
            KartKartCollision(p->getUserPointer(0)->getPointerKart(),
                              p->getContactPointCS(0),
                              p->getUserPointer(1)->getPointerKart(),
                              p->getContactPointCS(1)                );
            Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
            int kartid1 = p->getUserPointer(0)->getPointerKart()->getWorldKartId();
            int kartid2 = p->getUserPointer(1)->getPointerKart()->getWorldKartId();
            script_engine->runFunction("void onKartKartCollision(int, int)",
                [=](asIScriptContext* ctx) {
                    ctx->SetArgDWord(0, kartid1);
                    ctx->SetArgDWord(1, kartid2);
                });
            continue;
        }  // if kart-kart collision

        if(p->getUserPointer(0)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Kart hits physical object
            // -------------------------
            Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
            AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
            int kartId = kart->getWorldKartId();
            PhysicalObject* obj = p->getUserPointer(0)->getPointerPhysicalObject();
            std::string obj_id = obj->getID();
            std::string scripting_function = obj->getOnKartCollisionFunction();
            if (scripting_function.size() > 0)
            {
                script_engine->runFunction("void " + scripting_function + "(int, const string)",
                    [&](asIScriptContext* ctx) {
                        ctx->SetArgDWord(0, kartId);
                        ctx->SetArgObject(1, &obj_id);
                    });
            }
            if (obj->isCrashReset())
            {
                new RescueAnimation(kart);
            }
            else if (obj->isExplodeKartObject())
            {
                ExplosionAnimation::create(kart);
            }
            else if (obj->isFlattenKartObject())
            {
                const KartProperties* kp = kart->getKartProperties();
                kart->setSquash(kp->getSquashDuration() * kart->getPlayerDifficulty()->getSquashDuration(),
                    kp->getSquashSlowdown() * kart->getPlayerDifficulty()->getSquashSlowdown());
            }
            else if(obj->isSoccerBall() && 
                    race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
            {
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setLastKartTohitBall(kartId);
            }
            continue;
        }

        if (p->getUserPointer(0)->is(UserPointer::UP_ANIMATION))
        {
            // Kart hits animation
            ThreeDAnimation *anim=p->getUserPointer(0)->getPointerAnimation();
            if(anim->isCrashReset())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                new RescueAnimation(kart);
            }
            else if (anim->isExplodeKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                ExplosionAnimation::create(kart);
            }
            else if (anim->isFlattenKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                const KartProperties* kp = kart->getKartProperties();
                kart->setSquash(kp->getSquashDuration() * kart->getPlayerDifficulty()->getSquashDuration(),
                    kp->getSquashSlowdown() * kart->getPlayerDifficulty()->getSquashSlowdown());
            }
            continue;

        }
        // now the first object must be a projectile
        // =========================================
        if(p->getUserPointer(1)->is(UserPointer::UP_TRACK))
        {
            // Projectile hits track
            // ---------------------
            p->getUserPointer(0)->getPointerFlyable()->hitTrack();
        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Projectile hits physical object
            // -------------------------------
            Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
            Flyable* flyable = p->getUserPointer(0)->getPointerFlyable();
            PhysicalObject* obj = p->getUserPointer(1)->getPointerPhysicalObject();
            std::string obj_id = obj->getID();
            std::string scripting_function = obj->getOnItemCollisionFunction();
            if (scripting_function.size() > 0)
            {
                script_engine->runFunction("void " + scripting_function + "(int, int, const string)",
                        [&](asIScriptContext* ctx) {
                        ctx->SetArgDWord(0, (int)flyable->getType());
                        ctx->SetArgDWord(1, flyable->getOwnerId());
                        ctx->SetArgObject(2, &obj_id);
                    });
            }
            flyable->hit(NULL, obj);

            if (obj->isSoccerBall() && 
                race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
            {
                int kartId = p->getUserPointer(0)->getPointerFlyable()->getOwnerId();
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setLastKartTohitBall(kartId);
            }

        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_KART))
        {
            // Projectile hits kart
            // --------------------
            // Only explode a bowling ball if the target is
            // not invulnerable
            AbstractKart* target_kart = p->getUserPointer(1)->getPointerKart();
            PowerupManager::PowerupType type = p->getUserPointer(0)->getPointerFlyable()->getType();
            if(type != PowerupManager::POWERUP_BOWLING || !target_kart->isInvulnerable())
            {
                Flyable *f = p->getUserPointer(0)->getPointerFlyable();
                f->hit(target_kart);

                // Check for achievements
                AbstractKart * kart = World::getWorld()->getKart(f->getOwnerId());
                PlayerController *c = dynamic_cast<PlayerController*>(kart->getController());

                // Check that it's not a kart hitting itself (this can
                // happen at the time a flyable is shot - release too close
                // to the kart, and it's the current player. At this stage
                // only the current player can get achievements.
                if (target_kart != kart && c &&
                    c->getPlayer()->getConstProfile() == PlayerManager::getCurrentPlayer())
                {
                    // Compare the current value of hits with the 'hit' goal value
                    // (otherwise it would be compared with the kart id goal value,
                    // which doesn't exist.
                    PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_ARCH_ENEMY,
                                                       target_kart->getIdent(), 1, "hit");
                    if (type == PowerupManager::POWERUP_BOWLING)
                    {
                        PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_STRIKE,
                                                          "ball", 1);
                    }   // is bowling ball
                }   // if target_kart != kart && is a player kart and is current player
            }

        }
        else
        {
            // Projectile hits projectile
            // --------------------------
            p->getUserPointer(0)->getPointerFlyable()->hit(NULL);
            p->getUserPointer(1)->getPointerFlyable()->hit(NULL);
        }
    }  // for all p in m_all_collisions

    m_physics_loop_active = false;
    // Now remove the karts that were removed while the above loop
    // was active. Now we can safely call removeKart, since the loop
    // is finished and m_physics_world_active is not set anymore.
    for(unsigned int i=0; i<m_karts_to_delete.size(); i++)
        removeKart(m_karts_to_delete[i]);
    m_karts_to_delete.clear();

    PROFILER_POP_CPU_MARKER();
}   // update