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.
Based on the video it's something like this: Code (csharp): function Casteljau(p1 : Vector3, p2 : Vector3, p3 : Vector3, p4 : Vector3, iterations : int) { var stepping : float = 1.0 / iterations; for (var x : float = 0.0; x <= 1.0; x += stepping) { var ap1 : Vector3 = Vector3.Lerp(p1, p2, x); var ap2 : Vector3 = Vector3.Lerp(p2, p3, x); var ap3 : Vector3 = Vector3.Lerp(p3, p4, x); var bp1 : Vector3 = Vector3.Lerp(ap1, ap2, x); var bp2 : Vector3 = Vector3.Lerp(ap2, ap3, x); var p : Vector3 = Vector3.Lerp(bp1, bp2, x); // Place a vertex at p } }
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.
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): var p_0 : Transform; var p_1 : Transform; var p_2 : Transform; var p_3 : Transform; var iters : int; var point : GameObject; function start () { Casteljau (p_0,p_1,p_2,p_3,iters); } function Casteljau(P0 : Transform, P1 : Transform, P2 : Transform, P3 : Transform, iterations : int) { var stepping : float = 1.0 / iterations; for (var x : float = 0.0; x <= 1.0; x += stepping) { var Q0 : Vector3 = Vector3.Lerp(P0.position, P1.position, x); var Q1 : Vector3 = Vector3.Lerp(P1.position, P2.position, x); var Q2 : Vector3 = Vector3.Lerp(P2.position, P3.position, x); var R0 : Vector3 = Vector3.Lerp(Q0, Q1, x); var R1 : Vector3 = Vector3.Lerp(Q1, Q2, x); var B : Vector3 = Vector3.Lerp(R0, R1, x); point.transform.position = B; } } the white cubes are the control points and the black cube is suppose to be on the curve. Its not in this picture.
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/
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
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.
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?
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.
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.
You don't need to attach the script to a game object. Just call its functions from whichever script needs the curve data.
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 This is might not useful for creating tool but if you want to create a single curving animation, this is the simplest solution
here is a basic tutorial i slapped together yesterday (just click on unity icon and go to warrior difficuilty. and attached is the package
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?
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