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

Author Topic: [SOLVED]Holes between vertices on rotate  (Read 3705 times)

0 Members and 1 Guest are viewing this topic.

docwild

  • Newbie
  • *
  • Posts: 10
    • View Profile
[SOLVED]Holes between vertices on rotate
« on: July 20, 2014, 08:21:23 pm »
Hello.

So I have a problem with rotating vector of vertices. I've included a simple example and some screen shots.

#include <iostream>
#include <SFML/Graphics.hpp>

class BackGround : public sf::Drawable, public sf::Transformable
{
public:
    typedef std::vector<sf::Vertex> VertVec;
    BackGround() = delete;
    BackGround(sf::Image &im)
        :m_pType(sf::PrimitiveType::Points)
    {
        m_vertices.reserve(im.getSize().x * im.getSize().y);
        for(int y = 0; y < im.getSize().y; ++y)
        {
            for (int x = 0; x < im.getSize().x; ++x)
            {
                sf::Vertex vert(sf::Vector2f(x+0.5f,y+0.5f));
                vert.color = im.getPixel(x,y);
                m_vertices.push_back(vert);
            }
        }
    }

    ~BackGround(){}
private:

    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
    {
        // apply the entity's transform -- combine it with the one that was passed by the caller
        states.transform *= getTransform(); // getTransform() is defined by sf::Transformable

        // apply the texture
        states.texture = &m_texture;

        // you may also override states.shader or states.blendMode if you want


        // draw the vertex array
        target.draw(&m_vertices[0],m_vertices.size(),m_pType, states);

    }
    sf::Texture m_texture;
    VertVec m_vertices;
    sf::PrimitiveType m_pType;
};
int main()
{
    sf::RenderWindow win(sf::VideoMode(800,600),"PSIMPL",sf::Style::Close);
    sf::Image im,im2;
    im.loadFromFile("animage.png");

    BackGround bVert(im);


    bVert.setOrigin(400,300);
    bVert.move(400,300);

    while(win.isOpen())
    {
        sf::Event e;
        while (win.pollEvent(e))
        {
            if(e.type == sf::Event::Closed)
            {
                win.close();
            }
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::P))
        {
            im2 = win.capture();
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            bVert.move(sf::Vector2f(-1,0));
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            bVert.move(sf::Vector2f(1,0));
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            bVert.rotate(1);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            bVert.rotate(-1);
        }
        win.clear();
        win.draw(bVert);

        win.display();

    }
    im2.saveToFile("animage2.png");
    return 0;
}

 

Hopefully you can see that on rotation holes appear between the vertices. It gets worse between 45  degree increments before getting better at  90 degee steps.  It seems like some kind of rounding error but I am unsure how I can compensate, or if I can. It only seems to occur on rotation and not translation. Am I going about this the right way?

I'm only playing around really, seeing how far SFML is coming but I'm hoping to make a destructible terrain type thingy and I thought that keeping a screens worth of vertices would be ideal. The other option would be rendertexture but I think that would be fairly slow for my purposes.

This is happening with cutting edge master from github, mesa 10.2.3, arch linux and xf86-video-ati 1:7.4.0-2.
« Last Edit: July 20, 2014, 09:59:23 pm by docwild »

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Holes between vertices on rotate
« Reply #1 on: July 20, 2014, 08:29:49 pm »
You are converting an image into an array of vertices?
This, technically, is just a mass of points that are a pixel distance apart. When you rotate them, the points no longer match with the pixels. I'm not sure what your intentions are but rotating the image directly would work better ;) If you need to control individual pixels, you might want to consider making a square for each pixel rather than an infinitely small vertex.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

docwild

  • Newbie
  • *
  • Posts: 10
    • View Profile
Re: Holes between vertices on rotate
« Reply #2 on: July 20, 2014, 08:37:20 pm »
That was quick, thanks. Yes I'm mapping an image to the array so I can switch off pixels as I need to.  What you say makes sense but let me ask what you mean. Is it a 2x2 square for each pixel or a square (0.0f,0.0f,1.0f,1.0f).. 1x1?


Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Holes between vertices on rotate
« Reply #3 on: July 20, 2014, 09:28:45 pm »
In case my explanation wasn't clear, I thought I'd create this image to help. Even if you already understood it, it could help someone in the future  ;D



As for the creating a square per pixel, I mean a square - the size of the pixel, so 1x1 - for each pixel. I guess the middle diagram in my image shows what it would be like.

EDIT: corrected a spelling error in the image.
« Last Edit: July 20, 2014, 09:30:34 pm by Hapax »
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

docwild

  • Newbie
  • *
  • Posts: 10
    • View Profile
Re: Holes between vertices on rotate
« Reply #4 on: July 20, 2014, 09:59:01 pm »
Yes your solution and explanation does work. Thank you. Unfortunately moving from points to quads is just too expensive for my machine. I'll mark this as solved but I guess I'm back to experimenting.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: [SOLVED]Holes between vertices on rotate
« Reply #5 on: July 20, 2014, 10:16:12 pm »
Glad I was of some help.

Actually, you mentioned using a render texture. I think using a texture would be perfect for this. It scales the pixels as you scale the texture. However, it may be better to just use an image and then create a texture and sprite from that. That way, you should be able to control alpha values (switch pixels on and off).
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

docwild

  • Newbie
  • *
  • Posts: 10
    • View Profile
Re: [SOLVED]Holes between vertices on rotate
« Reply #6 on: July 20, 2014, 10:38:56 pm »
My intial tests with a render texture are positive.  At the moment I'm building a background from two images onto a RT and using the resulting texture as a sprite. When I want some of the foreground gone I'm creating a vertex array from the background image and blitting it onto the RT and then updating the sprites texture from that.

Sorry to be a pain but I'm not too clear on what you mean. Are you referring to creating a pixel array copied from part of the image, adjusting the alpha component for the pixels I'm interested in and updating the texture from that?

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: [SOLVED]Holes between vertices on rotate
« Reply #7 on: July 21, 2014, 12:03:58 am »
If you load the image from file into an sf::Image instead of an sf::Texture, you can then load the texture from the sf::Image instead of a file. With the sf::Image, you can either replace all of the pixels to whichever colour you want, which includes alpha - you can change the alpha of the colour of that pixel to zero and it'll be transparent (like when you load a png file with transparency) - or you can change only the alpha and leave the original colours.
I'm not sure of the performance cost of loading a texture from an image but it would only need to be done when it changes, I guess.

In short, instead of texture.loadFromFile(), try image.loadFromFile() then texture.loadFromImage(image), and adjust the alphas in the image's pixels' colour.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*