Search Unity

bezier curves through script

Discussion in 'Scripting' started by roger0, May 4, 2012.

  1. roger0

    roger0

    Joined:
    Feb 3, 2012
    Posts:
    1,208
    I'm trying to understand how to create bezier curves through script, so I can create new tools for my games. I have a general idea of how they work from wikipedia and this video http://www.youtube.com/watch?v=YATikPP2q70. Although, I have no clue as to where to start with the code.

    I'm very new to this type of math so I will need things to really be broken down for me. Basiclly, I want a tool that will draw out bezier curves in game.
     
    mekartikshah likes this.
  2. YosemiteSam

    YosemiteSam

    Joined:
    May 5, 2011
    Posts:
    60
    Based on the video it's something like this:

    Code (csharp):
    1. function Casteljau(p1 : Vector3, p2 : Vector3, p3 : Vector3, p4 : Vector3, iterations : int)
    2. {
    3.     var stepping : float = 1.0 / iterations;
    4.  
    5.     for (var x : float = 0.0; x <= 1.0; x += stepping)
    6.     {
    7.         var ap1 : Vector3 = Vector3.Lerp(p1, p2, x);
    8.         var ap2 : Vector3 = Vector3.Lerp(p2, p3, x);
    9.         var ap3 : Vector3 = Vector3.Lerp(p3, p4, x);
    10.        
    11.         var bp1 : Vector3 = Vector3.Lerp(ap1, ap2, x);
    12.         var bp2 : Vector3 = Vector3.Lerp(ap2, ap3, x);
    13.        
    14.         var p : Vector3 = Vector3.Lerp(bp1, bp2, x);
    15.        
    16.         // Place a vertex at p
    17.     }
    18. }
     
  3. roger0

    roger0

    Joined:
    Feb 3, 2012
    Posts:
    1,208
    What can you do with that script and where does it go? Could you explain whats going on?
     
  4. YosemiteSam

    YosemiteSam

    Joined:
    May 5, 2011
    Posts:
    60
    http://en.wikipedia.org/wiki/Bezier_curve#Higher-order_curves

    See the diagram here. P0, P1, P2 and P3 in the diagram correspond to p1, p2, p3 and p4 in the function. Q0, Q1 and Q2 correspond to ap1, ap2 and ap3. R0 and R1 correspond to bp1 and bp2. B corresponds to p.

    The points ap1, ap2 and ap3 are calculated by interpolating between the four control points. bp1 and bp2 are calculated by interpolating between the ap* points. And the final point where you want to place the vertex is calculated by interpolating between the bp* points.

    The bezier curve needs to be made of a finite number of line segments, and they need to be calculated all at once so there's a loop.

    With the final point p you need to add a vertex to a line segment primitive there.
     
  5. roger0

    roger0

    Joined:
    Feb 3, 2012
    Posts:
    1,208
    I believe I see the connection with the code and the ones on Wikipedia. Although, I still can't get results from the script. Below is an attempt to get the curve to show up in a somewhat visual way. What I'm expecting to happen is the ''point'' gameObject to snap to the location the curve is suppose to be. I don't know why the control points need to be passed in as an argument. I also don't understand whats going on with iterations and stepping. Why is stepping equaling 1 and being divided by iterations? Is iterations suppose to be the location on each line between 0 and 1?


    Code (csharp):
    1.  
    2. var p_0 : Transform;
    3.  
    4. var p_1 : Transform;
    5.  
    6. var p_2 : Transform;
    7.  
    8. var p_3 : Transform;
    9.  
    10. var iters : int;
    11.  
    12. var point : GameObject;
    13.  
    14. function start ()
    15. {
    16.  
    17. Casteljau (p_0,p_1,p_2,p_3,iters);
    18.  
    19. }
    20.  
    21.  
    22.  
    23. function Casteljau(P0 : Transform, P1 : Transform, P2 : Transform, P3 : Transform, iterations : int)
    24. {
    25.     var stepping : float = 1.0 / iterations;
    26.  
    27.     for (var x : float = 0.0; x <= 1.0; x += stepping)
    28.     {
    29.         var Q0 : Vector3 = Vector3.Lerp(P0.position, P1.position, x);
    30.         var Q1 : Vector3 = Vector3.Lerp(P1.position, P2.position, x);
    31.         var Q2 : Vector3 = Vector3.Lerp(P2.position, P3.position, x);
    32.        
    33.         var R0 : Vector3 = Vector3.Lerp(Q0, Q1, x);
    34.         var R1 : Vector3 = Vector3.Lerp(Q1, Q2, x);
    35.        
    36.         var B : Vector3 = Vector3.Lerp(R0, R1, x);
    37.        
    38.         point.transform.position = B;
    39.     }
    40. }
    the white cubes are the control points and the black cube is suppose to be on the curve. Its not in this picture.

     
    Last edited: May 5, 2012
  6. Poya

    Poya

    Joined:
    Jul 3, 2011
    Posts:
    51
    Given 4 points, the curve will usually not pass through the second and third points...they are just control points. So what you have actually looks kind of ok. You can try and draw a full curve to double check.

    Incidentally I was looking to have a camera dolly where I would specify some way points and have a smooth curve that actually passes through all of them. I found an article that explains how to do that, by generating additional control points. I wrote a post about it here:

    http://gamesforsoul.com/2012/05/putting-your-camera-on-a-dolly-in-unity/
     
  7. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    You could look into catmull rom splines. Here are some links that helped me doing this about a year ago. Look at Andee's curve_443 class, I promise you it works like a charm.

    Here is a thread I started with working code

    and

    Here is the thread to the class

    Hope this helps you further
     
  8. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,880
    this is a hermite spline function:
    This is the base of catmullrom, cardinal...etc splines.
    So, based on the above formula, you calculate a cardinal spline as follows:
    EDIT: Catmullrom is just the same as cardinal spline, but instead of t value, you use a constant 0.5f

    Simple as it sounds, Hope it helps.
     
    Last edited: May 5, 2012
  9. roger0

    roger0

    Joined:
    Feb 3, 2012
    Posts:
    1,208
    When I try to add andeeee's script to a gameObject it says cannot add script, needs to derive from monoBehavior. I switched the editor to UniSciTe but I get the same thing. Im also not sure how to implement your code, where do I put all those scripts?



    When I copy and paste your scripts into a C# file I get errors. Am I suppost to put them onto a gameObject? What are they suppost to do?
     
  10. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    Roger0

    How urgent do you need this? It will take me some time to dig up that project and look through what I did. A few things by just looking at those scripts: Note that the first one I posted runs a loop looking for all the gameobjects that has been tagged "beziercontrol" These objects are the actualt cubes that will determine the position of your spline connections. It is those positions that will be passed from that first function into the generateSegementArrays. Just read very carefully and figure out the program flow of that code.

    with reg to andees class, you will have to instantiate that class as an object in code, don't attach it to a game object. If you really battle I can see if I could put a tutorial together for this.
     
  11. roger0

    roger0

    Joined:
    Feb 3, 2012
    Posts:
    1,208
    Its not an emergency. Though, im really anxious to learn about bezier curves so I can produce some tools. I would love for someone to make a video tutorial of bezier splines. Theres none on the web for Unity.
     
  12. roger0

    roger0

    Joined:
    Feb 3, 2012
    Posts:
    1,208
    can anyone give me a hand?
     
  13. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    You don't need to attach the script to a game object. Just call its functions from whichever script needs the curve data.
     
  14. pus2meong

    pus2meong

    Joined:
    May 3, 2012
    Posts:
    83
    From the wikipedia link above, I create quadratic bezier curve using 3 sphere. I'm not that good on math formula so I decided to create the curve using the most easiest logic in my mind.

    Sphere1 will always pointing it Z axis to Sphere2, and Sphere2 will always pointing it Z axis to Sphere3.

    I use Trail Renderer component on Sphere1.
    I set the Sphere1 to move to Sphere2 and Sphere2 to Sphere3. With correct timing, I can create a curving line :)

    $easy curve.jpg

    This is might not useful for creating tool but if you want to create a single curving animation, this is the simplest solution :)
     
    Last edited: May 6, 2012
  15. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    here is a basic tutorial i slapped together yesterday (just click on unity icon and go to warrior difficuilty.

    and attached is the package
     

    Attached Files:

  16. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,374
    The bezier function chubbspet posted takes a range of 0 to 1 as an input (as all bezier algorithms do). However, I need the x coordinate as an input and find the corresponding y coordinate. Any ideas how to do this apart from a brute force approach?
     
  17. Varaughe

    Varaughe

    Joined:
    Apr 22, 2013
    Posts:
    40
    Check out "Runtime Curve Editor" from asset store, it's drawing curves in game having same shape equations like the built in editor from unity,when you try to edit Animation Curve or variations of different attributes from Particles System.All the code is available in the package ,so you may want to extract only the code for drawing bezier curves ingame.
    http://u3d.as/content/rus-artur-pfa/runtime-curve-editor/5C4
     
    mekartikshah likes this.