Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Clipping paths or masks  (Read 9733 times)

0 Members and 1 Guest are viewing this topic.

stubler

  • Newbie
  • *
  • Posts: 17
    • View Profile
Clipping paths or masks
« on: March 04, 2010, 11:44:37 pm »
I am very new to SFML and greatly appreciate the help I have received so far. My latest question concerns clipping paths or masks. I would like to create pan, zoom, rotate, and alpha blend effects within a defined region of the window. Referring to the picture below, consider that I have a full screen in which the background is a sprite  I would like to define regions of the screen in which I can use pan and zoom effects. For instance, I would like to be able to zoom into one of the faces in one of the foreground images while clipping the image to the white rectangle surrounding the foreground image, and leaving the background image completely intact.

Currently, I am only interested in rectangular clipping windows, however I could definitely imagine using arbitrary clipping paths if available.

Thanks for any advice you can share.
---Pete


model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
Clipping paths or masks
« Reply #1 on: March 05, 2010, 12:17:20 am »
Well, I suppose you could use SetSubRect on the sprite to clip to the region you want, and then use Scale to keep it the desired size.

I haven't tried it, though, so I don't know for sure.

stubler

  • Newbie
  • *
  • Posts: 17
    • View Profile
Should really try it.
« Reply #2 on: March 05, 2010, 01:35:35 am »
I have not tried it (I am home right now). However, I would expect the subrect to transform (scale and rotate) with the rest of the sprite. I will give it a go tomorrow morning, however.

UPDATE: I coded up an example and verified my expectation. The subrect does transform with the image. Thus, my question remains. How do I implement clipping paths or masks.

model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
Clipping paths or masks
« Reply #3 on: March 06, 2010, 05:50:51 am »
I am not quite sure what you mean, but I did an example for you that zooms and pans, using the sub rect, on top of a backgound sprite that uses the same image. There is some frame limiting code in there, because I just snagged the boiler plate from another project of mine, but I think you'll survive. ;)

Here it is:
Code: [Select]
/*************************************************************************************
** ZoomPanSubregion
**  Arrow keys pan, numpad +/- zooms in and out
*************************************************************************************/

#include <SFML/Graphics.hpp>

int main()
{
sf::RenderWindow window( sf::VideoMode(1024, 786, 32), "ZoomPanSubregion", sf::Style::Close );

// Loading the image
sf::Image image;
image.LoadFromFile( "wpf177b349.png" );

// The background sprite already has the same size as the window
sf::Sprite backgroundSprite( image );

// Foreground sprite is set up with the desired position and size
sf::Sprite foregroundsprite( image, sf::Vector2f( 50.f, 50.f ) );
foregroundsprite.Scale( .2f, .2f );

// Zoom factor decides how much 1 button click will zoom
float zoomFactor = 1.2f;

// Pan amount decides how much 1 button click will pan the image
int panAmount = 10;

// The desired minimum time between frames
const float &targetFrameRate = 1.f / 60.f;

while( window.IsOpened() )
{
// Make the frame rate constant
float frameTime = window.GetFrameTime();
if( frameTime < targetFrameRate )
sf::Sleep( targetFrameRate - frameTime );

sf::Event event;

while( window.GetEvent( event ) )
{
if( event.Type == sf::Event::Closed )
window.Close();

else if( event.Type == sf::Event::KeyPressed )
{
// Zooming
if( event.Key.Code == sf::Key::Subtract )
{
foregroundsprite.SetSubRect( sf::IntRect( foregroundsprite.GetSubRect().Left * zoomFactor,
 foregroundsprite.GetSubRect().Top * zoomFactor,
 foregroundsprite.GetSubRect().Right * zoomFactor,
 foregroundsprite.GetSubRect().Bottom * zoomFactor ) );

foregroundsprite.Scale( 1.f / zoomFactor, 1.f / zoomFactor );
}

else if( event.Key.Code == sf::Key::Add )
{
foregroundsprite.SetSubRect( sf::IntRect( foregroundsprite.GetSubRect().Left / zoomFactor,
 foregroundsprite.GetSubRect().Top / zoomFactor,
 foregroundsprite.GetSubRect().Right / zoomFactor,
 foregroundsprite.GetSubRect().Bottom / zoomFactor ) );

foregroundsprite.Scale( 1.f * zoomFactor, 1.f * zoomFactor );
}

// Panning
else if( event.Key.Code == sf::Key::Left )
foregroundsprite.SetSubRect( sf::IntRect( foregroundsprite.GetSubRect().Left - panAmount,
 foregroundsprite.GetSubRect().Top,
 foregroundsprite.GetSubRect().Right - panAmount,
 foregroundsprite.GetSubRect().Bottom ) );

else if( event.Key.Code == sf::Key::Right )
foregroundsprite.SetSubRect( sf::IntRect( foregroundsprite.GetSubRect().Left + panAmount,
 foregroundsprite.GetSubRect().Top,
 foregroundsprite.GetSubRect().Right + panAmount,
 foregroundsprite.GetSubRect().Bottom ) );

else if( event.Key.Code == sf::Key::Up )
foregroundsprite.SetSubRect( sf::IntRect( foregroundsprite.GetSubRect().Left,
 foregroundsprite.GetSubRect().Top - panAmount,
 foregroundsprite.GetSubRect().Right,
 foregroundsprite.GetSubRect().Bottom - panAmount ) );

else if( event.Key.Code == sf::Key::Down )
foregroundsprite.SetSubRect( sf::IntRect( foregroundsprite.GetSubRect().Left,
 foregroundsprite.GetSubRect().Top + panAmount,
 foregroundsprite.GetSubRect().Right,
 foregroundsprite.GetSubRect().Bottom + panAmount ) );
}

}

window.Clear();

window.Draw( backgroundSprite );
window.Draw( foregroundsprite );

window.Display();
}

return EXIT_SUCCESS;
}
Here is the (wedding) picture that I used: http://www.bojangles-guesthouse.co.uk/_wp_generated/wpf177b349.png

Of course, you will have to modify it a bit, if you want the zooming to happen around the center, for instance, but this should give you the general idea.

stubler

  • Newbie
  • *
  • Posts: 17
    • View Profile
Help for rotation?
« Reply #4 on: March 08, 2010, 04:21:13 pm »
Thanks model76, This great.

Unfortunately, I still need to be able to rotate the image within the clipping rectangle (leaving the rect in its original location in the window). Any other ideas.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Clipping paths or masks
« Reply #5 on: March 08, 2010, 05:15:07 pm »
This is not really possible in SFML 1. The best workaround, for rectangular clipping areas, is to use the OpenGL function glScissor.

In SFML 2 you can already do that with a RenderImage or a View, and I plan to implement true clipping masks.
Laurent Gomila - SFML developer

stubler

  • Newbie
  • *
  • Posts: 17
    • View Profile
One more thing... Documentation for SFML 2.0
« Reply #6 on: March 09, 2010, 04:13:32 pm »
Laurent,
Thanks for your help and all your work on SFML. Do you have any documentation on SFML 2 under development? I was able to access the SVN repository last night, however the doc directories are mostly empty. The "next version" of the online documentation appears to be for version 1.6.
Thanks again for all your help.
---Pete

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Clipping paths or masks
« Reply #7 on: March 09, 2010, 04:33:47 pm »
The documentation is generated automatically so it isn't stored on the repository anyway.

You can build it with doxygen, or simply read it directly in the headers.

There are no tutorials yet, however.
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Clipping paths or masks
« Reply #8 on: March 10, 2010, 01:25:08 pm »
Quote from: "Laurent"
and I plan to implement true clipping masks.

Sounds great. Do you already have an idea of the interface?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Clipping paths or masks
« Reply #9 on: March 10, 2010, 05:39:47 pm »
Quote
Do you already have an idea of the interface?

I have a very good idea of what the internal code will look like, but I'm not so sure about the public interface. Any suggestion ? :P
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Clipping paths or masks
« Reply #10 on: March 11, 2010, 03:40:23 am »
Indeed I have one:
Code: [Select]
sf::Drawable::SetClipping( const sf::FloatRect& localrect )
Easy and simple. ;)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Clipping paths or masks
« Reply #11 on: March 11, 2010, 07:55:56 am »
Quote from: "Tank"
Indeed I have one:
Code: [Select]
sf::Drawable::SetClipping( const sf::FloatRect& localrect )
Easy and simple. ;)

So you would associate a clipping mask to a drawable, in local coordinates?
I was rather thinking about adding it to the RenderTarget interface
Code: [Select]
target.SetClipping(mask);
target.Draw(...);
target.Draw(...);
...
target.SetClipping(none);


An other point is that it won't be limited to aligned rectangles, a clipping mask can be defined by one, two, three or four arbitrary lines. So I was thinking about implementing a sf::ClippingMask class that would provide functions for adding, removing and getting clipping lines (by the way, how would you call such a line? bound, boundary, limit, border, ...?).
Laurent Gomila - SFML developer

model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
Clipping paths or masks
« Reply #12 on: March 11, 2010, 11:37:26 am »
Quote from: "Laurent"
An other point is that it won't be limited to aligned rectangles, a clipping mask can be defined by one, two, three or four arbitrary lines.
Is it possible to make it more lines? An what about a circle? Or is this a limitation set by OpenGL?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Clipping paths or masks
« Reply #13 on: March 11, 2010, 02:42:35 pm »
Quote
Is it possible to make it more lines? An what about a circle? Or is this a limitation set by OpenGL?

With the technique that I intend to use I can have up to 6 clipping lines.
Laurent Gomila - SFML developer

gsaurus

  • Sr. Member
  • ****
  • Posts: 262
    • View Profile
    • Evolution Engine
Clipping paths or masks
« Reply #14 on: March 11, 2010, 07:22:37 pm »
I would say the target.SetClipping(mask) is the best option, so that you can draw a whole scene clipped with the same mask, which is the most common.

You can create a new generic shape/polygon class to be used both for current drawable shapes and for masks. You can also let maks be extended or to accept grayscale arrays/images for raster alpha channel masks.


Logical classes for polygon and vectors would be usefull, but may not fit with SFML current feel. I would prefer a way where images, shapes, and text logics are completely separated from the display concept (mvc). if we want to draw an image, we create a Sprite, but if we want to draw a shape, we could also create a kind of "sprite" for it, a drawable object with some specific properties for display. Same thing for text and masks. On this point of view, masks are a kind of view object that receives any of these logical objects (shapes, images, text)
Pluma - Plug-in Management Framework