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

Author Topic: SFML 3.0 future proof  (Read 2154 times)

0 Members and 1 Guest are viewing this topic.

Garwin

  • Jr. Member
  • **
  • Posts: 59
    • View Profile
SFML 3.0 future proof
« on: July 11, 2023, 02:10:16 pm »
I am preparing just a small project that will create Voronoi map from a set of points and create borderlines that can user define by layers (eg. gradients) and the owner of the "cell". After everything I am thinking of creating some noise so that borders will be not just lines from one Voronoi point to another.

I have already done the first part - the Voronoi diagram.



Right now there is the second part, transferring all this information to each cell, to each border (of the cell), and to each border line which can consist of several cells. Because borderline can have lots of points (after some noise is applied) and will not be changed often I think about using sf::VertexBuffer which will contain all border lines and will be drawn just one draw call.

However I would like it to do it as much as possible to close the prepared SFML 3.0 so that there will need no large refactoring. I know that there will be no quads in SFML 3.0 if I read it correctly, so any layers of borderline should be just triangles. Is it right?

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: SFML 3.0 future proof
« Reply #1 on: July 11, 2023, 04:15:13 pm »
This is pretty cool. I've recently looked at these sorts of things myself and they're very interesting indeed.

Right now there is the second part, transferring all this information to each cell, to each border (of the cell), and to each border line which can consist of several cells. Because borderline can have lots of points (after some noise is applied) and will not be changed often I think about using sf::VertexBuffer which will contain all border lines and will be drawn just one draw call.
This sounds like a good idea to avoid excess transferals from CPU memory to GPU memory.

However I would like it to do it as much as possible to close the prepared SFML 3.0 so that there will need no large refactoring. I know that there will be no quads in SFML 3.0 if I read it correctly, so any layers of borderline should be just triangles. Is it right?
Yes, you can use the triangles primitive and specify each one in turn. For an exact quad, this is still just two triangles. Basically, it's now 6 vertices per quad instead of 4 vertices per quad. Although, 2 of those vertices are identical to 2 of the others, of course.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Garwin

  • Jr. Member
  • **
  • Posts: 59
    • View Profile
Re: SFML 3.0 future proof
« Reply #2 on: July 11, 2023, 10:22:31 pm »
This is pretty cool. I've recently looked at these sorts of things myself and they're very interesting indeed.
It is really interesting but sometimes I think that my brain is just melting even if I find a lot of inspiration elsewhere. :-)
But I have still some issues with floating point math. :-(
There is no problem checking if the Voronoi diagram is correct (brute force is slow but probably error-prone, but I need to implement it and dump it to file what points break the math as till now the easiest way was just to look at a drawing of the Voronoi diagram to catch bugs) but the problem is the identification of these very extreme cases that break (and what is behind them). I have all math using floats with some fixed epsilon (this is not ideal but as standard usage will be around for points between 1e0 and 1e6 max. it should not be a problem) and I am thinking that I will switch private calculations to double precision and store only points as floats and all comparison will be done with floats.  I hope this will solve the issue as I expect that the final test will be about 1 million Voronoi diagrams with random points (min. distance 1 between points) and see if it will pass.

Right now there is the second part, transferring all this information to each cell, to each border (of the cell), and to each border line which can consist of several cells. Because borderline can have lots of points (after some noise is applied) and will not be changed often I think about using sf::VertexBuffer which will contain all border lines and will be drawn just one draw call.
This sounds like a good idea to avoid excess transferals from CPU memory to GPU memory.
I read in API documentation that there is a function that tests if sf::VertexBuffer is available. Just I do not know yet how can I do that if it is available it will use VertexBuffer but otherwise some standard type of array (probably std::vector)

However I would like it to do it as much as possible to close the prepared SFML 3.0 so that there will need no large refactoring. I know that there will be no quads in SFML 3.0 if I read it correctly, so any layers of borderline should be just triangles. Is it right?
Yes, you can use the triangles primitive and specify each one in turn. For an exact quad, this is still just two triangles. Basically, it's now 6 vertices per quad instead of 4 vertices per quad. Although, 2 of those vertices are identical to 2 of the others, of course.
[/quote]
Just a question, why quads will be depreciated? I do know not the details of OpenGL, is that reason that in actual SFML it still breaks quads to triangles which means unnecessary overheads?


Just writing this means that this first step is really more a small beginning if I look at what needs to be done to have really a lot of things just to get 100 % certainty about the correctness of Voronoi diagram and that there is a lot of math to create border lines, split them, merge them in case cells are removed or added and make some efficient sf::VertexBuffer that even changes of borders are just easy to update of the buffer.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: SFML 3.0 future proof
« Reply #3 on: July 11, 2023, 10:29:14 pm »
Just a question, why quads will be depreciated? I do know not the details of OpenGL, is that reason that in actual SFML it still breaks quads to triangles which means unnecessary overheads?
For one quads aren't part of the OpenGL ES specification, which is used on Android and iOS, so there you'll already get failures, thus we recommend to switch to triangles for maximum compatibility.
In the future, we will also in general upgrade the OpenGL version in use, and Quads won't be available there.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Garwin

  • Jr. Member
  • **
  • Posts: 59
    • View Profile
Re: SFML 3.0 future proof
« Reply #4 on: July 16, 2023, 02:47:18 pm »
I will really hate floating-point math.

I was just adding edges on the limiting rectangle. The first idea going through all Voronoi points than sorting them clockwise, adding corners, and making new edges seems simple.

I was completely wrong, it is much more complex.
I need to preserve information on which input points create that edge so I need to go through edges not Voronoi points thus new vector will have some points more times. Still not difficult and it will provide information which input points (cells) own the edge on limiting rectangle.

I tried it, it did not work. I try to find why and I found out that the issue is that these points on the edge of limiting area are not too close to be considered on edge by comparision function using floating point comparison through ulp. So my question was why. I have found that my calculation of these points are based on lineSegmentsIntersection function with edge line is AB and rectangle limiting line PQ:

    inline std::optional<Vector2f> lineSegmentsIntersection (const Vector2f pointA, const Vector2f pointB, const Vector2f pointP, const Vector2f pointQ)
    {
        double ux = pointB.x - pointA.x;
        double uy = pointB.y - pointA.y;
        double px = pointQ.x - pointP.x;
        double py = pointQ.y - pointP.y;

        double denom = ux * py - px * uy;
        if (compareToZero(denom) == std::partial_ordering::equivalent)
        {
            return std::nullopt; // Collinear
        }
        double a = (-uy * (pointA.x - pointP.x) + ux * (pointA.y - pointP.y)) / denom;
        double b = ( px * (pointA.y - pointP.y) - py * (pointA.x - pointP.x)) / denom;

        if (a >= 0 && a <= 1 && b >= 0 && b <= 1)
        {
            // intersection detected
            float x = pointA.x + (b * ux);
            float y = pointA.y + (b * uy);
            return Vector2f(x, y);
        }
        return std::nullopt;
}
 

Everything seems right but there is very small logical error. Intersection point is based on point A, not point P or Q which even if it is float it use integral inside as it is limiting rectangle for visualisation. So just swaping AB with PQ solves the problem.

I think I will have small pause and than I will go through all code to make it more readable before final check that it works for any points with reasonable distance between them.

But floating point math with completely different accuracy in different calculations makes comparison really extreme difficult.

At least next step is done. Voronoi should be completed, so now I will start to implement testing for large random numbers to verify that it handles all possible cases correctly.

« Last Edit: July 16, 2023, 03:48:53 pm by Garwin »