Ejemplo n.º 1
0
 /**
   * \brief Implementing callback from AbstractTopLevelContainer
   */
 virtual int getWidth()  { return m_area.getWidth(); }
Ejemplo n.º 2
0
// this function was written by Lonesome Ducky // modified to add clipping
// taken from http://irrlicht.sourceforge.net/forum/viewtopic.php?f=9&t=32388&start=15
void engine::draw2DImage(irr::video::IVideoDriver *driver, irr::video::ITexture* texture , irr::core::rect<irr::s32> sourceRect, irr::core::position2d<irr::s32> position, irr::core::position2d<irr::s32> rotationPoint, irr::f32 rotation, irr::core::vector2df scale, bool useAlphaChannel, irr::video::SColor color, irr::core::rect<irr::s32> clipRect) {
       
    irr::video::SMaterial material;

    // Store and clear the projection matrix
    irr::core::matrix4 oldProjMat = driver->getTransform(irr::video::ETS_PROJECTION);
    driver->setTransform(irr::video::ETS_PROJECTION,irr::core::matrix4());
       
    // Store and clear the view matrix
    irr::core::matrix4 oldViewMat = driver->getTransform(irr::video::ETS_VIEW);
    driver->setTransform(irr::video::ETS_VIEW,irr::core::matrix4());

    // Find the positions of corners
    irr::core::vector2df corner[8];

	float px = (irr::f32)position.X;
	float py = (irr::f32)position.Y;
	float pw = (irr::f32)sourceRect.getWidth();
	float ph = (irr::f32)sourceRect.getHeight();

    corner[0] = irr::core::vector2df(px,py);
	corner[1] = irr::core::vector2df(px + (pw * scale.X)/2,py);
    corner[2] = irr::core::vector2df(px+pw*scale.X,py);
	corner[3] = irr::core::vector2df(px,py+(ph * scale.Y)/2);
	corner[4] = irr::core::vector2df(px + pw*scale.X,py+(ph*scale.Y)/2);
    corner[5] = irr::core::vector2df(px,py+ph*scale.Y);
	corner[6] = irr::core::vector2df(px + (pw*scale.X)/2, py + ph*scale.Y);
    corner[7] = irr::core::vector2df(px+pw*scale.X,py+ph*scale.Y);

    // Rotate corners
    if (rotation != 0.0f)
        for (int x = 0; x < 8; x++)
            corner[x].rotateBy((irr::f32)rotation,irr::core::vector2df((irr::f32)rotationPoint.X, (irr::f32)rotationPoint.Y));

	irr::core::vector2df source_corners[8];
    source_corners[0] = irr::core::vector2df(0,0);
	source_corners[1] = irr::core::vector2df((float)sourceRect.getWidth()/2,0);
    source_corners[2] = irr::core::vector2df((float)sourceRect.getWidth(),0);
	source_corners[3] = irr::core::vector2df(0,(float)sourceRect.getHeight()/2);
	source_corners[4] = irr::core::vector2df((float)sourceRect.getWidth(),(float)sourceRect.getHeight()/2);
    source_corners[5] = irr::core::vector2df(0,(float)sourceRect.getHeight());
	source_corners[6] = irr::core::vector2df((float)sourceRect.getWidth()/2,(float)sourceRect.getHeight());
    source_corners[7] = irr::core::vector2df((float)sourceRect.getWidth(),(float)sourceRect.getHeight());

	// note: this assumes the rotation point is the actually center of the image
	float source_center_x = (float)sourceRect.getWidth()/2;
	float source_center_y = (float)sourceRect.getHeight()/2;

	// because there isn't a true to form clipping method available, I do this cludgy clipping method
	// first, I make the shape an octogon, then I clip the points of the rotated shape
	// then I find out what the source image ought to look like when clipped from those dimensions

	// 1. Find what the rotation the source rect corners would be
    if (rotation != 0.0f)
        for (int x = 0; x < 8; x++)
            source_corners[x].rotateBy((irr::f32)rotation,irr::core::vector2df(source_center_x, source_center_y));

	// 2. Clip the rotated shape
	for(int x=0; x < 8; x++){
		// these translations aren't correct for rotations that aren't vertical or horizontal. need to translate the points on the correct axis
		if(!clipRect.isPointInside(irr::core::vector2d<irr::s32>((irr::s32)source_corners[x].X + position.X, (irr::s32)source_corners[x].Y + position.Y))){
			if((source_corners[x].X + position.X) < clipRect.UpperLeftCorner.X){
				source_corners[x].X = (float)((float)clipRect.UpperLeftCorner.X - (float)position.X);
			}
			if((source_corners[x].X + position.X) > clipRect.LowerRightCorner.X){
				source_corners[x].X = (float)((float)clipRect.LowerRightCorner.X - (float)position.X);
			}
			if((source_corners[x].Y + position.Y) < clipRect.UpperLeftCorner.Y){
				source_corners[x].Y = (float)((float)clipRect.UpperLeftCorner.Y - (float)position.Y);
			}
			if((source_corners[x].Y + position.Y) > clipRect.LowerRightCorner.Y){
				source_corners[x].Y = (float)((float)clipRect.LowerRightCorner.Y - (float)position.Y);
			}
		}

		if(!clipRect.isPointInside(irr::core::vector2d<irr::s32>((irr::s32)corner[x].X, (irr::s32)corner[x].Y))){
			if(corner[x].X < clipRect.UpperLeftCorner.X){
				corner[x].X = (float)clipRect.UpperLeftCorner.X;				
			}
			if(corner[x].X > clipRect.LowerRightCorner.X){
				corner[x].X = (float)clipRect.LowerRightCorner.X; 
			}
			if(corner[x].Y < clipRect.UpperLeftCorner.Y){
				corner[x].Y = (float)clipRect.UpperLeftCorner.Y;
			}
			if(corner[x].Y > clipRect.LowerRightCorner.Y){
				corner[x].Y = (float)clipRect.LowerRightCorner.Y;
			}
		}
	}

	// 3. Rotate it back
    if (rotation != 0.0f)
        for (int x = 0; x < 8; x++)
            source_corners[x].rotateBy((irr::f32)rotation*-1,irr::core::vector2df(source_center_x, source_center_y));

	// 4. Use the UV Coordinates of the resulting shape
	irr::core::vector2df uvCorner[8];
	for (int x = 0; x < 8; x++)
		uvCorner[x] = source_corners[x];

    for (int x = 0; x < 8; x++) {
        float uvX = uvCorner[x].X/(float)texture->getSize().Width;
        float uvY = uvCorner[x].Y/(float)texture->getSize().Height;
        uvCorner[x] = irr::core::vector2df(uvX,uvY);
    }

	irr::video::S3DVertex vertices[8];

    // each indices is a point of a triangle to render
	// put them in the wrong order, and the triangle won't render right
	// I solved this puzzle one triangle at a time, to come up with this list
    irr::u16 indices[18] = { 0, 1, 3, 0, 2, 3, 3, 2, 4, 3, 4, 7, 3, 7, 6, 3, 6, 5 };

    // Convert pixels to world coordinates
    float screenWidth = (float)driver->getScreenSize().Width;
    float screenHeight = (float)driver->getScreenSize().Height;

    for (int x = 0; x < 8; x++) {
        float screenPosX = ((corner[x].X/screenWidth)-0.5f)*2.0f;
        float screenPosY = ((corner[x].Y/screenHeight)-0.5f)*-2.0f;

        vertices[x].Pos = irr::core::vector3df(screenPosX,screenPosY,1);
        vertices[x].TCoords = uvCorner[x];
        vertices[x].Color = color;
    }

    material.Lighting = false;
    material.ZWriteEnable = false;
    material.ZBuffer = false;
    material.TextureLayer[0].Texture = texture;
    material.MaterialTypeParam = irr::video::pack_texureBlendFunc(irr::video::EBF_SRC_ALPHA, irr::video::EBF_ONE_MINUS_SRC_ALPHA, irr::video::EMFN_MODULATE_1X, irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR);

    if (useAlphaChannel)
        material.MaterialType = irr::video::EMT_ONETEXTURE_BLEND;
    else
        material.MaterialType = irr::video::EMT_SOLID;

    driver->setMaterial(material);
	driver->drawIndexedTriangleList(&vertices[0],8,&indices[0],6);

    // Restore projection and view matrices
    driver->setTransform(irr::video::ETS_PROJECTION,oldProjMat);
    driver->setTransform(irr::video::ETS_VIEW,oldViewMat);
}
Ejemplo n.º 3
0
 /**
   * \brief Implementing callback from AbstractTopLevelContainer
   */
 virtual int getHeight() { return m_area.getHeight(); }
//----------------------------------------------------------------------------//
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);
}