Hi!
I've been using SFML recently and found it to be really great
The only concern I have right now, is that it lacks the ability to render a simple arbitrary quad on the screen.
I mean, for each of the 4 vertices : arbitrary position, arbitrary uv coordinates and arbitrary color.
So I wrote a sf::Quad class that does just that.
Usage :
sf::Quad quad;
quad.SetImage(...);
// Set on screen coordinates (absolute)
quad.SetVertexPosition(0, sf::Vector2f(0, 0));
quad.SetVertexPosition(1, sf::Vector2f(64,0));
quad.SetVertexPosition(2, sf::Vector2f(0, 64));
quad.SetVertexPosition(3, sf::Vector2f(64,64));
// Set uv coordinates (normalized)
quad.SetVertexUVs(0, sf::Vector2f(0,0));
quad.SetVertexUVs(1, sf::Vector2f(1,0));
quad.SetVertexUVs(2, sf::Vector2f(0,1));
quad.SetVertexUVs(3, sf::Vector2f(1,1));
// Set color
quad.SetVertexColor(0, sf::Color::Red);
quad.SetVertexColor(1, sf::Color::Green);
quad.SetVertexColor(2, sf::Color::Blue);
quad.SetVertexColor(3, sf::Color::Magenta);
I'm not familiar with SFML's coding conventions, but I tried to mimic what I saw in sf::Sprite. Hope it fits well.
Anyway, here you are (based on SFML-2.0 15/06/2010 snapshot) :
Quad.hpp
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_QUAD_HPP
#define SFML_QUAD_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Resource.hpp>
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Rect.hpp>
namespace sf
{
class Image;
////////////////////////////////////////////////////////////
/// \brief Like Sprite, but allows control of the four
/// vertices that composes the Quad (position, color,
/// texture coordinates).
///
////////////////////////////////////////////////////////////
class SFML_API Quad : public Drawable
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates an empty quad with no source image.
///
////////////////////////////////////////////////////////////
Quad();
////////////////////////////////////////////////////////////
/// \brief Construct the quad from a source image
///
/// \param image Source image, that the sprite will display
/// \param color Global color of the sprite
///
/// \see SetImage
///
////////////////////////////////////////////////////////////
explicit Quad(const Image& image, const Color& color = Color(255, 255, 255, 255));
////////////////////////////////////////////////////////////
/// \brief Change the source image of the quad
///
/// The \a image argument refers to an image that must
/// exist as long as the quad uses it. Indeed, the quad
/// doesn't store its own copy of the image, but rather keeps
/// a pointer to the one that you passed to this function.
/// If the source image is destroyed and the quad tries to
/// use it, it may appear as a white rectangle.
///
/// \param image New image
///
/// \see GetImage
///
////////////////////////////////////////////////////////////
void SetImage(const Image& image);
////////////////////////////////////////////////////////////
/// \brief Set the global color of the object
///
/// This global color affects the entire object, and modulates
/// (multiplies) its original pixels.
/// The default color is white.
///
/// \param color New color
///
/// \see GetColor
///
////////////////////////////////////////////////////////////
void SetColor(const Color& color);
////////////////////////////////////////////////////////////
/// \brief Change the position of a vertex
///
/// The vertex position is relative to the sprite's position.
///
/// \param index Index of the vertex
/// \param color New color of the vertex
///
////////////////////////////////////////////////////////////
void SetVertexPosition(unsigned int index, const Vector2f& pos);
////////////////////////////////////////////////////////////
/// \brief Change the color of a vertex
///
/// \param index Index of the vertex
/// \param color New color of the vertex
///
////////////////////////////////////////////////////////////
void SetVertexColor(unsigned int index, const Color& color);
////////////////////////////////////////////////////////////
/// \brief Change the uv coordinates of a vertex
///
/// \param index Index of the vertex
/// \param uv The UV coordinates of the vertex
///
////////////////////////////////////////////////////////////
void SetVertexUVs(unsigned int index, const Vector2f& uv);
////////////////////////////////////////////////////////////
/// \brief Get the source image of the sprite
///
/// If the sprite has no source image, or if the image
/// doesn't exist anymore, a NULL pointer is returned.
/// The returned pointer is const, which means that you can't
/// modify the image when you retrieve it with this function.
///
/// \return Pointer to the sprite's image
///
/// \see SetImage
///
////////////////////////////////////////////////////////////
const Image* GetImage() const;
////////////////////////////////////////////////////////////
/// \brief Get the position of a vertex
///
/// The vertex position on the screen is absolute and
/// doesn't depend on the actual quad's position.
///
/// \param index Index of the vertex
///
/// \return Position of the vertex
///
////////////////////////////////////////////////////////////
const Vector2f& GetVertexPosition(unsigned int index) const;
////////////////////////////////////////////////////////////
/// \brief Get the color of a vertex
///
/// \param index Index of the vertex
///
/// \return Color of the vertex
///
////////////////////////////////////////////////////////////
const Color& GetVertexColor(unsigned int index) const;
////////////////////////////////////////////////////////////
/// \brief Get the uv coordinates of a vertex
///
/// \param index Index of the vertex
///
/// \return UV coordiantes of the vertex
///
////////////////////////////////////////////////////////////
const Vector2f& GetVertexUVs(unsigned int index) const;
protected :
////////////////////////////////////////////////////////////
/// \brief Draw the object to a render target
///
/// \param target Render target
/// \param renderer Renderer providing low-level rendering commands
///
////////////////////////////////////////////////////////////
virtual void Render(RenderTarget& target, Renderer& renderer) const;
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
struct Vertex
{
Vertex(const Vector2f& pos = Vector2f(0, 0), const Vector2f& uv = Vector2f(0, 0), const Color& color = Color(255, 255, 255));
Vector2f Position;
Color Col;
Vector2f UV;
};
ResourcePtr<Image> myImage; ///< Image used to draw the quad
Vertex myV[4]; ///< Array of vertices
};
} // namespace sf
#endif // SFML_QUAD_HPP
////////////////////////////////////////////////////////////
/// \class sf::Quad
///
/// sf::Quad is a drawable class that allows to display an
/// image (or a part of it) on a render target just like
/// sf::Sprite, but with increased flexibility, at the cost
/// of ease of use.
///
/// Most functions from sf::Drawable are hidden: position,
/// rotation, scale and origin. Color and blend mode are
/// still available.
///
/// It is important to note that, like sf::Sprite, the
/// sf::Quad instance doesn't copy the image that it uses,
/// it only keeps a reference to it.
/// Thus, a sf::Image must not be destructed while it is
/// used by a sf::Quad (i.e. never write a function that
/// uses a local sf::Image instance for creating a quad).
///
/// Usage example:
/// \code
/// // Declare and load an image
/// sf::Image image;
/// image.LoadFromFile("image.png");
///
/// // Create a sprite
/// sf::Quad quad;
/// quad.SetImage(image);
/// quad.SetVertexPosition(0, sf::Vector2f(0, 0));
/// quad.SetVertexPosition(1, sf::Vector2f(16,0));
/// quad.SetVertexPosition(2, sf::Vector2f(0, 16));
/// quad.SetVertexPosition(3, sf::Vector2f(16,16));
///
/// // Display it
/// window.Draw(quad); // window is a sf::RenderWindow
/// \endcode
///
/// \see sf::Image
///
////////////////////////////////////////////////////////////
Quad.cpp :
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Quad.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/Renderer.hpp>
#include <utility>
namespace sf
{
////////////////////////////////////////////////////////////
Quad::Quad()
{
}
////////////////////////////////////////////////////////////
Quad::Quad(const Image& image, const Color& color) :
Drawable (Vector2f(0,0), Vector2f(1,1), 0, color)
{
SetImage(image);
}
////////////////////////////////////////////////////////////
void Quad::SetImage(const Image& image)
{
// If there was no valid image before, force adjusting to the new image size
bool adjustToNewSize = false;
if (!myImage)
adjustToNewSize = true;
// Assign the new image
myImage = ℑ
// If we want to adjust the size and the new image is valid, we adjust the source rectangle
if (adjustToNewSize && (image.GetWidth() > 0) && (image.GetHeight() > 0))
{
FloatRect coords = myImage->GetTexCoords(IntRect(0, 0, image.GetWidth(), image.GetHeight()));
float left = coords.Left;
float top = coords.Top;
float right = coords.Left + coords.Width;
float bottom = coords.Top + coords.Height;
myV[0].UV = Vector2f(left, top);
myV[1].UV = Vector2f(right, top);
myV[2].UV = Vector2f(left, bottom);
myV[3].UV = Vector2f(right, bottom);
}
}
////////////////////////////////////////////////////////////
void Quad::SetColor(const Color& color)
{
Drawable::SetColor(color);
}
////////////////////////////////////////////////////////////
void Quad::SetVertexPosition(unsigned int index, const Vector2f& pos)
{
myV[index].Position = pos;
}
////////////////////////////////////////////////////////////
void Quad::SetVertexColor(unsigned int index, const Color& color)
{
myV[index].Col = color;
}
////////////////////////////////////////////////////////////
void Quad::SetVertexUVs(unsigned int index, const Vector2f& uv)
{
myV[index].UV = uv;
}
////////////////////////////////////////////////////////////
const Image* Quad::GetImage() const
{
return myImage;
}
////////////////////////////////////////////////////////////
const Vector2f& Quad::GetVertexPosition(unsigned int index) const
{
return myV[index].Position;
}
////////////////////////////////////////////////////////////
const Color& Quad::GetVertexColor(unsigned int index) const
{
return myV[index].Col;
}
////////////////////////////////////////////////////////////
const Vector2f& Quad::GetVertexUVs(unsigned int index) const
{
return myV[index].UV;
}
////////////////////////////////////////////////////////////
void Quad::Render(RenderTarget&, Renderer& renderer) const
{
// Bind the texture
renderer.SetTexture(myImage);
renderer.Begin(Renderer::TriangleStrip);
for (unsigned int i = 0; i < 4; ++i)
renderer.AddVertex(myV[i].Position.x, myV[i].Position.y, myV[i].UV.x, myV[i].UV.y, myV[i].Col);
renderer.End();
}
////////////////////////////////////////////////////////////
Quad::Vertex::Vertex(const Vector2f& pos, const Vector2f& uv, const Color& color) : Position(pos), Col(color), UV(uv)
{
}
} // namespace sf