//----------------------------------------------------------------------------// 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); }