Sign in to follow this  
VanillaSnake21

C++ How to correctly scale a set of bezier curves?

Recommended Posts

I've got a working implementation of 4d and 1d bezier curve font generator, however I'm not sure how to now transition into actually making text. As of right now I create my font by clicking and dragging control vertices on the screen, once I have a few curves aligned I designate it as a letter and save the font. But I'm not sure what coordinate system to use to make sure that I can scale the existing curves to any size? I'm thinking to have the letter sit in like a canonical box with -1 to 1 in both x and y, but then how do I re normalize the curves and still have the ability to plot points directly on screen? As of right now the control vertices are in viewport space of [0 to screen dimention], so when I plot a point I just take the client mouse coordinates. But if I choose to project the final letter to -1 to 1 space, I can only do so once I draw all the curves for that letter as I need the bounding box of all the curves. So what is the right way to approach this? 

 

This is probably a bit convoluted, the point of the question is how do I transition from font editor to actual font. Do I have to unproject the curves when I open them in font editor and duplicate as working copies and only bake the final normalized letter into the font when I'm done editing it or else how would I do it at runtime?

Edited by VanillaSnake21

Share this post


Link to post
Share on other sites

I'm not sure what you ask for, but in any case you seem to reinvent things that have common standarts e.g. TrueType and Postscript, sou you should find some answers by looking at their specs.

I wonder why you don't use those standarts, as there are font editors and also libs to render those fonts with graphics APIs, probably all for free.

One main problem is the horizontal distance between letters. AFAIK this is solved by default left/right bounds, but there are also individual settings for custom pairs of letter, e.g. "LA" should be as close together as possible, while "IL" should have some space between. (I know this from bitmap fonts typical for games like http://www.angelcode.com/products/bmfont/ , probably vector fonts do the same)

Share this post


Link to post
Share on other sites

It's my own framework, I'm not willing to use anything but the most low level libraries, as I'm not even using a graphics api. My question was how to represent the spline correctly internally so it could both be used in letter glyphs as well as modified in the editor. I've settled on having a duplicate structure at this point, I have one representation for a spline when I'm dragging around it's vertices in the editor and another normalized representation for when it's rendered, I was just looking for a single elegant implementation in this question. 

Share this post


Link to post
Share on other sites

Why can't your editor just use normalized coordinates, too? After any change to the spline's control points, compute the correct normalization factor to return everything to the unit square, and apply it/redraw.

Share this post


Link to post
Share on other sites
57 minutes ago, ApochPiQ said:

Why can't your editor just use normalized coordinates, too? After any change to the spline's control points, compute the correct normalization factor to return everything to the unit square, and apply it/redraw.

 

Because I can't normalize until I get the final shape of the letter, lets say letter A. Takes 3 curves, / -- \  , if I just renormalize after I add the second curve, the structure shifts to renormalized units, meaning it shifts to the center of the canonical box as I have it now, so I have to manually renormalize once I finalize the letter. That's how I have it now, it's a bit tedious and I was looking for a way to maybe use alternate coordinate systems to have a more elegant implementation, but not every piece of code has to be perfect I guess, just have to settle on this for now.

Share this post


Link to post
Share on other sites
7 hours ago, VanillaSnake21 said:

It's my own framework, I'm not willing to use anything but the most low level libraries

JoeJ was not saying to adopt the standards or adopt libraries that implement the standard, he was suggesting to just look at how they solved the same problem as a source of inspiration.

Share this post


Link to post
Share on other sites
9 hours ago, Alberth said:

JoeJ was not saying to adopt the standards or adopt libraries that implement the standard, he was suggesting to just look at how they solved the same problem as a source of inspiration.

 I mean suggesting to dig through a mature open source library code to see how it does a certain specific action is a bit of an overkill imo. If there are some docs you can point me to that deal with this issue, that's another thing.

Share this post


Link to post
Share on other sites

Maybe looking at example rendering implementations linked at the angelcode webpage helps. (Probably all OpenGL, but it would be the same for a software renderer.) The data per letter is pretty self explaining.

But i don't know if this would help with your problem - i still have no idea what the problem is exactly. Probably it's the same with others. I think you should provide screenshots from your tool and / or some illustration to visualize your problem.

Share this post


Link to post
Share on other sites
7 hours ago, JoeJ said:

Maybe looking at example rendering implementations linked at the angelcode webpage helps. (Probably all OpenGL, but it would be the same for a software renderer.) The data per letter is pretty self explaining.

But i don't know if this would help with your problem - i still have no idea what the problem is exactly. Probably it's the same with others. I think you should provide screenshots from your tool and / or some illustration to visualize your problem.

 

It's not easy to explain or even draw or demonstrate, I'll try again but bear with me. When I'm making a font in my editor I do so by plotting single control vertices. For every click I create a single control vertex, after I plot 4 of them it makes a 4d bezier curve. Now how do I store the actual positions of the control vertex? Right now I just have them as exact mouse coordinates where I clicked on the screen so CV1(100px, 100px) CV2( 300px, 300px) and so on until CV4 which now makes a curve. These are all in screen space. Now I add a few more curve lets say which form a letter, so all these curves are being manipulated in pixel coordinates. So now if I want to actually use these letters and scale them to any font size, I can't use these screen coordinates anymore, I have to fit the letter in some scalable space like 0 to 1. So I have to convert all the vertex coordinates into that space. Right now I'm doing that manually, I just have a button in my editor called Normalize, so once I'm happy with the letter I've formed, I click normalize and it transforms all the vertices into normalized 0 to 1 space. My question was whether I can avoid doing the normalization manually and work in some space that is normalized from the get go. As in when I plot the point with the mouse, I wouldn't store the location of the mouse as the vertex coordinate, but right away transoform the mouse coordinate into a normalized space. I hope that clears up what my intentions with the question were. It's not really a problem as everything works just fine as of now, I just wanted to know if there is a more elegant way of doing this.

Share this post


Link to post
Share on other sites

There can be no magic solution.

You want arbitrary sized splines that are normalized. No math can predict how big you will make your splines; to normalize you must by definition know how big the spline is.

The compromise is to draw boundaries ahead of time and force all characters in your font to adhere to predefined dimensions. If you know a glyph's size ahead of time you can draw its splines in normal space.

But you can't have arbitrary glyph dimensions and also eliminate the need for explicit normalization steps.

Share this post


Link to post
Share on other sites

Yeah, but the bounding rect (or normalization square - however we call it) needs to be part of the editing process anyways. To be more clear, the user needs to specify left and right bounds an the base line manually. The baseline ensures all letters like 'mn' have the same bottom height. A letter like 'g' is lower than the baseline and a algorithm can't get the base just from calculating bounds. A letter like 'o' is a tiny bit lower (and higher) than 'nm' too, so it does not appear smaller than other letters to the eye. The user should set those bounds and he should be able to tweak them later until he is happy with the result. So it's like with any other form of content creation: You keep the original data and convert it to game asset anytime the artist does any changes.

Share this post


Link to post
Share on other sites

Oh so I should contain all the curves in a region and just map it from 0 to 1. Right, that makes sense. I guess come to think of it every font editor has set size glyphs, not sure why I thought I needed arbitrary sizes inside the editor. Thanks. Also @JoeJ, I didn't consider the baseline and letter metrics, thanks.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Forum Statistics

    • Total Topics
      627722
    • Total Posts
      2978804
  • Similar Content

    • By SR D
      I've been learning how to do vertex buffers plus index buffers using Ogre, but I believe this is mostly the same across several engines. I have this question about using vertex buffers + index buffers.
      Using DynamicGeometryGameState (from Ogre) as an example, I noticed that when drawing the cubes, they were programmatically drawn in order within the createIndexBuffer() function like so ...
       
      const Ogre::uint16 c_indexData[3 * 2 * 6] = { 0, 1, 2, 2, 3, 0, //Front face 6, 5, 4, 4, 7, 6, //Back face 3, 2, 6, 6, 7, 3, //Top face 5, 1, 0, 0, 4, 5, //Bottom face 4, 0, 3, 3, 7, 4, //Left face 6, 2, 1, 1, 5, 6, //Right face };
      From the above, the front face is drawn using the vertices 0, 1, 2, 2, 3, 0. But when reading in thousands of vertices from a file, one obviously doesn't code an array specifying which vertices make up a face.
      So how is this done when working with a large number of vertices?
    • By Josheir
      I am working on a SFML c++ program that uses two rendering windows passed from main to the function drawmessage in a class textmessage.  I was using the second window for displaying debug information that is displayed because I could not get the appropriate information from the SFML object.
      With that said, here is the part of that function that works the first time through and does not on the second usage.  I really have changed the code to try and get it working.   For example I created the two objects locally here for testing.  I am sorry about the extra commented statements they help convey the message too.
      There is the same problem though, the statement :     string test =     message_holder10.getString(); is working and shows "asty" on every run.  On the first run of the program there is a display of the text correctly however on the second call there is no display of it.  (I am stepping through until the display command.)
      I feel like I have exhausted my tries so I am asking for help please.
      If it is the font I will just die, I really don't think it is.
       
       
       
                  sf::Text message_holder10;
                  sf::RenderWindow windowtype3(sf::VideoMode(700, 1000), "a");

                  if ((space_is_used && on_last_line) || (space_is_used && ((line_number) == (total_lines - 2))))
                  {

                      //string temp_string = message::Get_Out_Bound_String();
                      //int length_of_string = temp_string.length();
                      sf::Font Fontforscore;
                      if (gflag == 0)
                      {
                          gflag = 1;
                          
                          if (!Fontforscore.loadFromFile("ARIALBD.ttf"))
                          {
                              exit(1);
                          }

                          message_holder10.setFont(Fontforscore);
                          message_holder10.setCharacterSize(100);
                          message_holder10.setFillColor(sf::Color::Red);
                          message_holder10.setOrigin(0, 0);
                          message_holder10.setPosition(0, 0);
                          windowtype2.close();
                      }
                      message_holder10.setString("asty");
                          
                          //int y_for_space = display_y_setting + (total_lines - 2) * each_vertical_offset_is;
                          //int this_width = 0;
                          
                          //float x = message_holder.getLocalBounds().width;

                          
                          
                          //message_holder.setPosition( ( (first_width - x )/2), y_for_space);
                          
                  
                          //windowtype2.close();

                          string test =     message_holder10.getString();
                          
                          windowtype3.clear();
                          windowtype3.draw(message_holder10);
                          windowtype3.display();
                          
                          
                           
       
                          //windowtype.display();
                      

                       Wait_For_Space_Press();
                      
       
      /////////////////////////
       
      Before, the :      windowtype3.display()  without the clear was drawing other text in this call, just not this one particular text message with it!
       
      Thank you so much I am wondering what it can be,
       
      Josheir
    • By Tispe
      Hi
      I want to test out a polymorphic entity component system where the idea is that the components of an entity are "compositioned" using templated multiple inheritance. But I am running into an issue because I am stacking a bunch of methods with the same names inside a class (but they have different signatures). I want these methods to be overloaded by the template type but my compiler says the access is ambiguous. I have issues making them unambiguous with the using declaration because the paramter pack expansion causes a syntax error.
      Can anyone here give me some advice on this?
       
      template <class T> class component { T m_data; protected: component() {}; ~component() {}; public: void set(const T& data) { m_data = data; }; }; template <class ...Ts> class entity : public component<Ts>... { public: entity() {}; ~entity() {}; //using component<Ts>::set...; // syntax error }; struct position { float x{}; float y{}; float z{}; }; struct velocity { float x{}; float y{}; float z{}; }; int main() { entity<position, velocity> myEntity; position pos = { 1.0f, 1.0f, 1.0f }; velocity vel = { 2.0f, 2.0f, 2.0f }; myEntity.set(pos); // error C2385: ambiguous access of 'set' //myEntity.set(vel); return 0; }  
    • By Baemz
      Hello,
      I've been working on some culling-techniques for a project. We've built our own engine so pretty much everything is built from scratch. I've set up a frustum with the following code, assuming that the FOV is 90 degrees.
      float angle = CU::ToRadians(45.f); Plane<float> nearPlane(Vector3<float>(0, 0, aNear), Vector3<float>(0, 0, -1)); Plane<float> farPlane(Vector3<float>(0, 0, aFar), Vector3<float>(0, 0, 1)); Plane<float> right(Vector3<float>(0, 0, 0), Vector3<float>(angle, 0, -angle)); Plane<float> left(Vector3<float>(0, 0, 0), Vector3<float>(-angle, 0, -angle)); Plane<float> up(Vector3<float>(0, 0, 0), Vector3<float>(0, angle, -angle)); Plane<float> down(Vector3<float>(0, 0, 0), Vector3<float>(0, -angle, -angle)); myVolume.AddPlane(nearPlane); myVolume.AddPlane(farPlane); myVolume.AddPlane(right); myVolume.AddPlane(left); myVolume.AddPlane(up); myVolume.AddPlane(down); When checking the intersections I am using a BoundingSphere of my models, which is calculated by taking the average position of all vertices and then choosing the furthest distance to a vertex for radius. The actual intersection test looks like this, where the "myFrustum90" is the actual frustum described above.
      The orientationInverse is the viewMatrix in this case.
      bool CFrustum::Intersects(const SFrustumCollider& aCollider) { CU::Vector4<float> position = CU::Vector4<float>(aCollider.myCenter.x, aCollider.myCenter.y, aCollider.myCenter.z, 1.f) * myOrientationInverse; return myFrustum90.Inside({ position.x, position.y, position.z }, aCollider.myRadius); } The Inside() function looks like this.
      template <typename T> bool PlaneVolume<T>::Inside(Vector3<T> aPosition, T aRadius) const { for (unsigned short i = 0; i < myPlaneList.size(); ++i) { if (myPlaneList[i].ClassifySpherePlane(aPosition, aRadius) > 0) { return false; } } return true; } And this is the ClassifySpherePlane() function. (The plane is defined as a Vector4 called myABCD, where ABC is the normal)
      template <typename T> inline int Plane<T>::ClassifySpherePlane(Vector3<T> aSpherePosition, float aSphereRadius) const { float distance = (aSpherePosition.Dot(myNormal)) - myABCD.w; // completely on the front side if (distance >= aSphereRadius) { return 1; } // completely on the backside (aka "inside") if (distance <= -aSphereRadius) { return -1; } //sphere intersects the plane return 0; }  
      Please bare in mind that this code is not optimized nor well-written by any means. I am just looking to get it working.
      The result of this culling is that the models seem to be culled a bit "too early", so that the culling is visible and the models pops away.
      How do I get the culling to work properly?
      I have tried different techniques but haven't gotten any of them to work.
      If you need more code or explanations feel free to ask for it.

      Thanks.
       
    • By AyeRonTarpas
      A friend of mine and I are making a 2D game engine as a learning experience and to hopefully build upon the experience in the long run.

      -What I'm using:
          C++;. Since im learning this language while in college and its one of the popular language to make games with why not.     Visual Studios; Im using a windows so yea.     SDL or GLFW; was thinking about SDL since i do some research on it where it is catching my interest but i hear SDL is a huge package compared to GLFW, so i may do GLFW to start with as learning since i may get overwhelmed with SDL.  
      -Questions
      Knowing what we want in the engine what should our main focus be in terms of learning. File managements, with headers, functions ect. How can i properly manage files with out confusing myself and my friend when sharing code. Alternative to Visual studios: My friend has a mac and cant properly use Vis studios, is there another alternative to it?  
  • Popular Now