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

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Critkeeper

Pages: [1] 2 3 ... 5
1
I'm not basing my reasoning on it being calculated on the cpu.

It doesn't matter where it is calculated, and as a matter of fact SFML does calculate transforms on the CPU. It just happens to format its matrices in a way that conforms with opengl.

2
Quote
if you had functions for each possible order, 24 functions in all, you could compute a transform for an arbitrary shear around a point, rotation around a point, scale around a point and translation in whatever order all while only making a single function call.
Ok... and why would we do that? What's your point? You should have started this very long post by explaining your intentions, instead of losing us in your maths ;)

It would just make the library a bit faster and allow users to use all the transformation capabilities of SFML without doing matrix multiplication even once.

Typical libraries provide translation, rotation, and scale. (most don't include shear)
In order to rotate around a point you have to do two matrix multiplications. One to translate the point so that it overlaps the origin, then rotate, then translate back-- this produces a transform matrix that is effectively the same as those transformations in that order; all you have to do is multiply your vector by that transform matrix and voila, you just rotated about a specific point.

SFML provides a function that uses that specific transform matrix, called rotate and which takes both the angle and the point about which to rotate. Ditto for scale. It also provides normal translation.

If you still want to combine scale and translation, or scale and rotation, or rotation and scale, in a specific order, then you have to do old fashion matrix multiplication by using the provided multiplication operator.

Matrix multiplication is kind of slow. Part of the reason SFML provides rotations about a point is because it is convenient, the other reason is that it is faster to just use a premultplied matrix like that than it is to do basic tranlsation, then basic rotation, then translate back. Doing the former involves multplying a matrix by a vector and one function call. Doing the latter involves multiplying a vector by a matrix, and multplying a matrix by a matrix by a matrix, and 4 function calls.

Basically what I am saying is we can take it a step further. Instead of having "rotate about a point" and "scale about a point" and "translate"

We could have:

"RotateScaleTranslate( args for rotation, args for scale, args for translation)"
"RotateTranslateScale( args for rotation, args for scale, args for translation)"
"ScaleRotateTranslate( args for rotation, args for scale, args for translation)"
"ScaleTranslateRotate( args for rotation, args for scale, args for translation)"
"TranslateRotateScale( args for rotation, args for scale, args for translation)"
"TranslateScaleRotate( args for rotation, args for scale, args for translation)"

For example, the first function first rotates, then scales, and then translates. If the implementation did matrix*matrix multiplication underneath in order to generate the appropriate transform matrix, then there wouldn't be much point in using it aside from the fact that you don't have to mess around with the multiplication operator yourself in order to do rotation then scale then translation. With what I am recommending, it would NOT do matrix*matrix multiplication underneath, the transformation matrix would be precomputed and baked into the function.

If you think about it, there are no other combinations of doing these operations. There are only 6 permutations for the given 3 operations, and translation operations can be added by adding the operands (ditto for scale and rotation) so strictly speaking the user really shouldn't have to fool around with matrix multiplication in order to do combinations of those transformations in a specific order; he just needs to know about those 6 specific transformation matrices and thats all.

Thats what I'm saying. The user shouldn't have to fool around with matrix multiplication in order to do all the combinations of transforms that exist in 2d in SFML for scale, translate, and rotate.

If you want to throw in shear, the number jumps from 6 to 24 (compare 3! and 4!), that still isn't too bad, but you can't really afford to throw in another transformation operation beyond that.

3
Transformable code keeps track of what transforms have been applied and updates the transform if need be.

Transform code provides methods for combined translation and rotation, and combined translation and scale.

For example, suppose we have a method called translate and rotate that does what you'd expect, and which returns a fresh new Transform with the given data.

Rotating around a point with the method rotate(angle, centerX, centerY) will return a transform that is exactly the same as matrix multiplication of translate(centerX, centerY) * rotate(angle, 0, 0) * translate(-centerX, -centerY). In fact thats how the matrix expression for the combined translation rotation was generated. Formula for basic rotation around the origin, scaling around the origin, shearing around the origin and translating can be found on wikipedia, and they can be matrix multiplied to generate other matrices.

"Rotating around a given center" or "Scaling around a given center" are so common that it makes sense for us to combine the formula and provide it as rotate(angle, centerX, centerY), which is exactly what SFML does.

So I was wondering why not just combine all of the transforms that way and throw in shear for good measure, using the standard opengl style of matrix order? For example, a shear around a point, followed by a rotation around a different point, followed by a scale around a third point, followed by a translation:

Code: [Select]
typedef
struct
{
        float v[16];
} Transform;

Transform
transform
(       float shcx
,       float shcy
,       float shvx
,       float shvy
,       float rcx
,       float rcy
,       float angle
,       float sccx
,       float sccy
,       float scvx
,       float scvy
,       float tx
,       float ty
)
{
        const float cosine = cos (angle);
        const float sine = sin (angle);
        const float a = -shvy * scvx * sine + scvx * cosine;
        const float b = shvx * scvx * cosine - scvx * sine;
        const float c = shvy * scvy * cosine + scvy * sine;
        const float d = shvx * scvy * sine + scvy * cosine;
        const float x = tx + scvx * (rcx * (1 - cosine) + rcy * sine) + shvy * scvx * shcy * sine - shvx * scvx * shcx * cosine + sccx * (1 - scvx);
        const float y = ty + scvy * (rcy * (1 - cosine) + rcy * sine) - shvx * scvy * shcx * sine - shvy * scvy * shcy * cosine + sccy * (1 - scvy);
        const Transform r =
        {       a,      c,      0,      0
        ,       b,      d,      0       0
        ,       0,      0,      1,      0
        ,       x,      y,      0,      1
        };
        return r;
}
(notice in the above struct initialization you have to conceptually flip the math matrix across the perceived diagonal. If you format it in a list and look at the indexes you will see that it maps correctly to opengl's way of doing things)

I don't know if this will be useful to anyone here, or whether using it (well namely the method of generating it) could speed up the implementation of SFML Transformable as I haven't really given it much thought.

Here is how I generated the equations:




The left most matrix is obviously a scale(k,h) around point(s,t), the right most is a shear(f,g) around point (q,r), and the middle is rotation(theta) around point(x,y).

The resulting matrix is specifically what you would get for first shearing, then rotating, then scaling around specific points.
The function I provided tacks on translation after doing those three things in that specific order (translation as a last operation is fairly simple and not worth typing out so I didn't, in general you would need to multiply the transformation matrix as well)

Note that you get a different matrix if you want to do those things in a different order. All in all there are 4 operations, so there are 4! = 24 unique transformation matrices, which would be generated similar to the above one, gotten by multiplying 4 matrices together, one matrix for each fundamental kind of operation: rotation about a point, translation, shear about a point and scale about a point, in all possible different orders.

if you had functions for each possible order, 24 functions in all, you could compute a transform for an arbitrary shear around a point, rotation around a point, scale around a point and translation in whatever order all while only making a single function call. And 24 isn't so high that you'd thrash the I-Cache.

Just food for thought.

4
General discussions / Why use SFML over SDL?
« on: July 12, 2015, 08:10:43 am »
This spicy question isn't meant to give you heartburn. I just want side by side comparison of these two libraries from someone who has used both and knows their strengths and weaknesses.

5
General / Re: Fastest way to update screen from pixels.
« on: June 21, 2015, 06:24:46 pm »
Well, what I want to achieve is a little more complicated. I want to make an isometric engine that sorts pixels by the depth they appear on scene and alpha composites the result, so for each screen pixel coordinate in the screen i need to check if it belongs to a sprite and if it does, add it to an array of pixels at that position, then sort the pixels in this array based on it's depth, calculated elsewhere.

I've searched for alternative methods, that would use GLSL. But due to it's big limitations (like lack of ability to store sampler objects in an array) it seems impossible.

a typical 1080p monitor has 1080 * 1920 = 2073600 pixels.

You are talking about having 2073600 arrays of at most size N, where N is the upper bound on the number of times a sprite can be overlapped by another sprite-- or you are talking about 2073600 dynamically growing vectors.

Not only do you have 2073600 vectors, you will need to update each of them 60 times per second if you intend to maintain 60 frames per second.

That means you will only have 8 nano seconds to update each array.

Not going to happen in this decade bro.

6
General / Re: Programming puzzle / quiz.
« on: June 21, 2015, 04:31:40 pm »
The index must be a constant expression. You can write a function template func<N, M>(tuple) that wraps get<M>(get<N>(tuple)). But as Hiura says, it's going to be ugly, especially since you mix tuples with arrays.

Code: [Select]
template <int s, int i, class... Types>
typename tuple_element <s, tuple_element<i, tuple<Types...>>&>::type&
get ( tuple <Types...>& T )
{
    return get <i> (get <s> (T));
}

7
General / Programming puzzle / quiz.
« on: June 21, 2015, 03:30:20 pm »
suppose i have a tuple containing tuples and arrays

Code: [Select]
tuple
< tuple
< map<int, int>
, float
>
, tuple
< int
, int
>
, array
< int
5
>
, tuple
< vector<int>
, queue<float>
>
>
state;

the normal way to access an element in a tuple is to use

Code: [Select]
get <Index> (tuple);
so for the above, to access the array I would use

Code: [Select]
get <2> (state);
but in order to access the 3rd element of the array I would have to say:

Code: [Select]
get <3> ( get <2> (state) );
this is quite ugly.


here is an imaginary function that looks prettier:

Code: [Select]
get <3> (state, 2);
what would the full function signature for such a function look like?

8
General / How would I initialize a RenderWindow inside a tuple?
« on: June 19, 2015, 10:15:33 am »
Code: [Select]
tuple
<   RenderWindow
>
interface
{   RenderWindow (VideoMode(1920, 1080), "") };

Before anyone says "why would you want ... " just don't. I could use window.create(), but I want to be sure that what I'm trying to do isn't actually possible. The compiler spits out complaints about RenderWindow being noncopyable.

How would I initialize a tuple element without performing a copy? In other words, how do I emplace an element into a tuple?

9
of ints.

This isn't a request or a complaint, and it doesn't need to be since this is just General Discussion.

I'm just curious. I want to understand the reasoning behind the design decisions of SFML, since I regard it as one of the cleanest libraries I have ever seen; I hope that by understanding the reasons behind various design decisions I can pull some of that good hygiene into my own work.

Code: [Select]
namespace sf
   39 {
   44 class Event
   45 {
   46 public:
   47
   52     struct SizeEvent
   53     {
   54         unsigned int width; 
   55         unsigned int height;
   56     };
   57
   62     struct KeyEvent
   63     {
   64         Keyboard::Key code;   
   65         bool          alt;     
   66         bool          control;
   67         bool          shift;   
   68         bool          system; 
   69     };
   70
   75     struct TextEvent
   76     {
   77         Uint32 unicode;
   78     };
   79
   84     struct MouseMoveEvent
   85     {
   86         int x;
   87         int y;
   88     };
   89
   95     struct MouseButtonEvent
   96     {
   97         Mouse::Button button;
   98         int           x;     
   99         int           y;     
  100     };
  101
  109     struct MouseWheelEvent
  110     {
  111         int delta;
  112         int x;     
  113         int y;     
  114     };
  115
  120     struct MouseWheelScrollEvent
  121     {
  122         Mouse::Wheel wheel;
  123         float        delta;
  124         int          x;     
  125         int          y;     
  126     };
  127
  133     struct JoystickConnectEvent
  134     {
  135         unsigned int joystickId;
  136     };
  137
  142     struct JoystickMoveEvent
  143     {
  144         unsigned int   joystickId;
  145         Joystick::Axis axis;       
  146         float          position;   
  147     };
  148
  154     struct JoystickButtonEvent
  155     {
  156         unsigned int joystickId;
  157         unsigned int button;     
  158     };
  159
  164     struct TouchEvent
  165     {
  166         unsigned int finger;
  167         int x;               
  168         int y;               
  169     };
  170
  175     struct SensorEvent
  176     {
  177         Sensor::Type type;
  178         float x;           
  179         float y;           
  180         float z;           
  181     };
  182
  187     enum EventType
  188     {
  189         Closed,                 
  190         Resized,               
  191         LostFocus,             
  192         GainedFocus,           
  193         TextEntered,           
  194         KeyPressed,             
  195         KeyReleased,           
  196         MouseWheelMoved,       
  197         MouseWheelScrolled,     
  198         MouseButtonPressed,     
  199         MouseButtonReleased,   
  200         MouseMoved,             
  201         MouseEntered,           
  202         MouseLeft,             
  203         JoystickButtonPressed, 
  204         JoystickButtonReleased,
  205         JoystickMoved,         
  206         JoystickConnected,     
  207         JoystickDisconnected,   
  208         TouchBegan,             
  209         TouchMoved,             
  210         TouchEnded,             
  211         SensorChanged,         
  212
  213         Count                   
  214     };
  215
  217     // Member data
  219     EventType type;
  220
  221     union
  222     {
  223         SizeEvent             size;             
  224         KeyEvent              key;               
  225         TextEvent             text;             
  226         MouseMoveEvent        mouseMove;         
  227         MouseButtonEvent      mouseButton;       
  228         MouseWheelEvent       mouseWheel;       
  229         MouseWheelScrollEvent mouseWheelScroll; 
  230         JoystickMoveEvent     joystickMove;     
  231         JoystickButtonEvent   joystickButton;   
  232         JoystickConnectEvent  joystickConnect;   
  233         TouchEvent            touch;             
  234         SensorEvent           sensor;           
  235     };
  236 };
  237
  238 } // namespace sf

See the (x,y) pairs everywhere? Why not use sf::Vect ?

10
No, you would obviously zero out one of the dimensions of the mesh so that it is just a 2d connected triangle soup.

11
As was already said, there's no common file formats, as such we would have to create our own format, which is definitely not what SFML is made for.

http://en.wikipedia.org/wiki/OpenCTM

We provide texture loading because there are common formats and because these formats are the standard way to provide image information, as such everyone would have to write the same code.

It looks to me like there is a bunch of different texture formats that people use, including and not limited to .png, .bmp, .jpg  etc. They don't just provide different behaviour, they are different formats.

So pick a few widely used 3d mesh formats, and treat 2d triangle soup as a 3d mesh with zeroed out third dimension.

Collada is another format you could use.

12
Oh really? because it looks an awful lot to me like a texture is just an array of color information. And you can load and store textures, therefore you are loading and storing arrays of color information.

VertexArray is hardly any different than ColorArray (ergo, texture) from a fundamental point of view.

Why not make it easier on the client by allowing them to load and store arrays of vertex information?


How usable would SFML be if the ability to load and store textures were taken away, and you had to do it per pixel? People would just end up writing their own load and store methods. Its the same exact thing with vertexes.

13
How the heck is loading and storing an array of vertex information high level?

I mean c'mon.

Stop trying to come up with fake reasons and give me a real reason. "SFML is low level" is just a one size fits all cop-out response to any suggestion.

I value the simplicity of SFML and I value its utility. You have to balance these two things carefully. Too much utility and your library will be bloated and complicated. Too much simplicity and people will just write everything themselves because your library doesn't provide the necessary utilities to be convenient.

Its a matter of convenience. Loading and storing vertex information and render state information would be convenient.

14
No information in a computer is readable without some kind of editor or viewer. A text editor. A graphics editor. A vertex editor.

A vertex parser would be trivial, and so would the rest of what I suggest. A sprite class is also trivial if all its components have already been implemented, so why make a sprite class a part of the library? Because it makes the library easier to use and the cost of adding it is not high in terms of added complexity or time.

My question is why not make my suggestion a part of the library? It makes skinning GUI and characters easier, and it makes a few other tricks easier too, like loading animation sequences (sequences of changes in vertex and texture information)

15
Well for example, suppose you want to be able to persistently change the texture coordinates for a vertexArray without having to recompile your code. If vertexArray were a loadable resource, you could just change the data in that resource. This means you can change not only the textures of your entities in your compiled and shipped application through data, but also their shape.

You can change the texture coordinates of all the vertices in the vertexArray to point to something else in the same texture map, like a new skin for your character or object or GUI or whatever. Again, you could even change the shape and all other vertex qualities. You would want this information to persist. If the resource is savable/loadable you could easily make it persist without any trouble at all.


Pages: [1] 2 3 ... 5
anything