예제 #1
0
//----------------------------------------------------------------------------//
void IrrlichtGeometryBuffer::setupClipping() const
{
    // NB: This is done via viewport & projection manipulation because Irrlicht
    // does not expose scissoring facilities of underlying APIs.  This has the
    // unfortunate side effect of being much more expensive to set up.
    d_savedViewport = d_driver.getViewPort();
    d_savedProjection = d_driver.getTransform(irr::video::ETS_PROJECTION);

    const Sizef csz(d_clipRect.getSize());
    const Sizef tsz(static_cast<float>(d_savedViewport.getWidth()),
                     static_cast<float>(d_savedViewport.getHeight()));

    // set modified projection 'scissor' matix that negates scale and
    // translation that would be done by setting the viewport to the clip area.
    irr::core::matrix4 scsr(irr::core::matrix4::EM4CONST_IDENTITY);
    scsr(0, 0) = tsz.d_width / csz.d_width;
    scsr(1, 1) = tsz.d_height / csz.d_height;
    scsr(3, 0) = d_xViewDir * (tsz.d_width + 2.0f *
                   (d_savedViewport.UpperLeftCorner.X -
                     (d_clipRect.left() + csz.d_width * 0.5f))) / csz.d_width;
    scsr(3, 1) = -(tsz.d_height + 2.0f *
                   (d_savedViewport.UpperLeftCorner.Y -
                     (d_clipRect.top() + csz.d_height * 0.5f))) / csz.d_height;

    scsr *= d_savedProjection;
    d_driver.setTransform(irr::video::ETS_PROJECTION, scsr);

    // set new viewport for the clipping area
    const irr::core::rect<irr::s32> vp(
            static_cast<irr::s32>(d_clipRect.left()),
            static_cast<irr::s32>(d_clipRect.top()),
            static_cast<irr::s32>(d_clipRect.right()),
            static_cast<irr::s32>(d_clipRect.bottom()));
    d_driver.setViewPort(vp);
}
//----------------------------------------------------------------------------//
void IrrlichtGeometryBuffer::draw() const
{
    // Set up clipping for this buffer
    //
    // NB: This is done via viewport & projection manipulation because Irrlicht
    // does not expose scissoring facilities of underlying APIs.  This has the
    // unfortunate side effect of being much more expensive to set up.
    const irr::core::rect<irr::s32> target_vp(d_driver.getViewPort());
    const irr::core::matrix4 proj
        (d_driver.getTransform(irr::video::ETS_PROJECTION));

    const Size csz(d_clipRect.getSize());
    const Size tsz(static_cast<float>(target_vp.getWidth()),
                   static_cast<float>(target_vp.getHeight()));

    // set modified projection 'scissor' matix that negates scale and
    // translation that would be done by setting the viewport to the clip area.
    irr::core::matrix4 scsr(irr::core::matrix4::EM4CONST_IDENTITY);
    scsr(0, 0) = tsz.d_width / csz.d_width;
    scsr(1, 1) = tsz.d_height / csz.d_height;
    scsr(3, 0) = d_xViewDir * (tsz.d_width + 2.0f *
                   (target_vp.UpperLeftCorner.X -
                     (d_clipRect.d_left + csz.d_width * 0.5f))) / csz.d_width;
    scsr(3, 1) = -(tsz.d_height + 2.0f *
                   (target_vp.UpperLeftCorner.Y -
                     (d_clipRect.d_top + csz.d_height * 0.5f))) / csz.d_height;
    scsr *= proj;
    d_driver.setTransform(irr::video::ETS_PROJECTION, scsr);

    // set new viewport for the clipping area
    const irr::core::rect<irr::s32> vp(
            static_cast<irr::s32>(d_clipRect.d_left),
            static_cast<irr::s32>(d_clipRect.d_top),
            static_cast<irr::s32>(d_clipRect.d_right),
            static_cast<irr::s32>(d_clipRect.d_bottom));
    d_driver.setViewPort(vp);

    if (!d_matrixValid)
        updateMatrix();

    d_driver.setTransform(irr::video::ETS_WORLD, d_matrix);

    const int pass_count = d_effect ? d_effect->getPassCount() : 1;
    for (int pass = 0; pass < pass_count; ++pass)
    {
        // set up RenderEffect
        if (d_effect)
            d_effect->performPreRenderFunctions(pass);

        // draw the batches
        size_t pos = 0;
        BatchList::const_iterator i = d_batches.begin();
        for ( ; i != d_batches.end(); ++i)
        {
            d_material.setTexture(0, (*i).first);
            d_driver.setMaterial(d_material);
            d_driver.drawIndexedTriangleList(&d_vertices[pos], (*i).second,
                                            &d_indices[pos], (*i).second / 3);
            pos += (*i).second;
        }
    }

    // clean up RenderEffect
    if (d_effect)
        d_effect->performPostRenderFunctions();

    // restore original projection matrix and viewport.
    d_driver.setTransform(irr::video::ETS_PROJECTION, proj);
    d_driver.setViewPort(target_vp);
}