PDA

View Full Version : Creating your own MMouse... Bezier Spline



pwnaz0r
11-20-2007, 11:31 PM
Creating your own Move Mouse via Bezier Spline

Ok, well understanding the spline path algorithms can sometimes be confusing, so if you ever get a little overwhelmed during this tutorial, please take a deep breath and read that little part over again. I will try to make this as easy to understand as possible with visuals.


In the Beginning...

Alright, so just starting out with Splines? Ready to make your own custom move mouse? Well you have come to the right place. I will be explaining an algorythm for the Cubic Bezier Spline in order to produce a human like curve for the Move Mouse.

The Bezier Spline is also known as NURBS (Non - Uniform Rational Bezier Spline). It uses an equation using what is known as Control Points, or the points that regulate the mouse path. You can have any number of control points, but I suggest that you make that number four. The first Control Point is always the starting position of you mouse, and the last control point is always the end of your line.



The History of the Bezier Spine

I try not to just copy things to show that I understand them fully. However, I feel it necessary for you to understand why NURBS were made.


Development of NURBS (Non Uniform Rational Basis, or Bézier Spline) began in the 1950s by engineers who were in need of a mathematically precise representation of freeform surfaces like those used for car bodies and ship hulls, which could be exactly reproduced whenever technically needed. Prior representations of this kind of surface only existed as a single physical model created by a designer.

The pioneers of this development were Pierre Bézier who worked as an engineer at Renault, and Paul de Casteljau who worked at Citroën, both in France. Bézier worked nearly parallel to de Casteljau, neither knowing about the work of the other. But because Bézier published the results of his work, the average computer graphics user today recognizes splines — which are represented with control points lying off the curve itself — as Bézier splines, while de Casteljau’s name is only known and used for the algorithms he developed to evaluate parametric surfaces. In the 1960s it became clear that non-uniform, rational B-splines are a generalization of Bézier splines, which can be regarded as uniform, non-rational B-splines.

At first NURBS were only used in the proprietary CAD packages of car companies. Later they became part of standard computer graphics packages.

Real-time, interactive rendering of NURBS curves and surfaces were first made available on Silicon Graphics workstations in 1989. In 1993, the first interactive NURBS modeller for PCs, called NöRBS, was developed by CAS Berlin, a small startup company cooperating with the Technical University of Berlin. Today most professional computer graphics applications available for desktop use offer NURBS technology, which is most often realized by integrating a NURBS engine from a specialized company.


.


Understanding Control Points

Control Points are simply points that the spline will follow. For instance, if you put two control points right in the middle of the line of a Mouse Path, you will get a straight line.

http://img156.imageshack.us/img156/152/onmiddleqf0.png.



As you move the Control Points away from the middle of the line, your path will be more spline.

http://img410.imageshack.us/img410/646/offset1tm8.png.


You can always put the control points behind outside the two start and end points, which will result in a cut-back, (like curving the mouse backwards and forwards like so), but I find it easier to just start at a higher theta, which I will explain later in the tutorial.


http://img441.imageshack.us/img441/5135/offset2ac6.png


There are not many things you can do with control points. You need to have a slight understanding of the coordinate system used in SCAR to use them.

The main reason that people hate using Control Points is because YOU HAVE TO FIGURE OUT SOME WAY TO PLACE THEM. Its actually very simple. Simply google "Control Point Detection" or something to that extent and find a procedure made for it, or make one your own!



Understanding Theta

Theta is, to be put simply, the regulator of your spline. When you are creating points along a line, you have to have step correct? Theta is your "step" kind of. Here is the best way to explain it: Theta is an extended value, from 0.0 to 1.0. It defines where your point is on the line. For instance, in a normal NURBS, the startpoints theta value is 0.0, the endpoints theta value 1.0, and the midpoints value is 0.5. Look at the picture below for more clarification.

http://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Bezier_3_big.gif/240px-Bezier_3_big.gif

Since all Bezier splines follow this pattern, we find our step formula for this. If you wish to make a wind mouse like Benland, I will show you how to do that later. However, for now we are looking for a smooth, standard function. In the following SCAR tags, we will be finding what is called the theta increase. When making a spline path, you will have to have to increase theta as you go along the line correct? Well here is how to find it.


theta_Inc:= 1.0 div Distance; // really the equation is 1.0 - 0.0 div Distance


the reason the equation is really 1.0 - 0.0 because you do the total theta value of them divided by the distance you are traveling, but that doesn't concern you :).

So basically, as theta increases, the "current point" along the line is moved closer to the endpoint.



Creating the Spline Path Function


Ok, so lets start out with a core function. I have the basic variables commented and declared here.



function Spline(ex, ey: integer; CTRLP1, CTRLP2: TPoint): TPointArray;
var
theta, theta_Inc: extended; //must be extended;
sx, sy: integer; //start x and y
Dist: integer; //distance between startpoint and endpoint.
begin
GetMousePos(sx, sy); //Get your start point.
Dist:= Distance(sx, sy, ex, ey);
end;


CtrlP1 and 2 are the two center control points. End X and End Y are going to be your last control point and Start X and Start Y are going to be your start point.

now, you are going to want to put your ctrlpoints all into one array, like so.


function Spline(ex, ey: integer; CTRLP1, CTRLP2: TPoint): TPointArray;
var
theta, theta_Inc: extended; sx, sy: integer;
Dist: integer;
CtrlPoints: Array [1..4] of TPoint; //Added, Control Points array.
begin
GetMousePos(sx, sy);
Dist:= Distance(sx, sy, ex, ey);
CtrlPoints[1]:= Point(sx, sy);
CtrlPoints[2]:= CtrlP1;
CtrlPoints[3]:= CtrlP2;
CtrlPoints[4]:= Point(ex, ey);
end;


now, you set theta's value at 0.0, and use a repeat statement. I will use a little line that will make sure I don't go over 1.0 theta, think about it for a second and you will understand.

function Spline(ex, ey: integer; CTRLP1, CTRLP2: TPoint): TPointArray;
var
theta, theta_Inc: extended; sx, sy: integer;
Dist: integer;
CtrlPoints: Array [1..4] of TPoint; //Added, Control Points array.
begin
GetMousePos(sx, sy);
Dist:= Distance(sx, sy, ex, ey);
CtrlPoints[1]:= Point(sx, sy);
CtrlPoints[2]:= CtrlP1;
CtrlPoints[3]:= CtrlP2;
CtrlPoints[4]:= Point(ex, ey);
theta_inc:= 1.0 div Dist;
theta:= 0.0;
repeat
theta_Inc:= MinE(1.0 - theta, theta_Inc); //This is the line to stop theta over 1.0
theta:= theta + theta_Inc;
until(Theta >= 1.0);
result[High(result)]:= Point(ex, ey); //This is a failsafe. High = Length - 1.
end;


now, here is where you will need to equation for finding a point on a Quadratic Spline using theta. Since you have come this far, I will supply you with this equation :D.


function PointOnCubicBezier(cp: TPointArray; t, Curve: Extended): TPoint;
var
ax, ay, bx, by, cx, cy,
tSquared, tCubed: Extended;
i: integer;
begin
cx := Curve * (cp[1].x - cp[0].x);
bx := Curve * (cp[2].x - cp[1].x) - cx;
ax := cp[3].x - cp[0].x - cx - bx;

cy := Curve * (cp[1].y - cp[0].y);
by := Curve * (cp[2].y - cp[1].y) - cy;
ay := cp[3].y - cp[0].y - cy - by;

tSquared := t * t;
tCubed := tSquared * t;

result.x := Round((ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x);
result.y := Round((ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y);
end;


function Spline(ex, ey: integer; CTRLP1, CTRLP2: TPoint): TPointArray;
var
theta, theta_Inc: extended; sx, sy: integer;
Dist: integer;
CtrlPoints: Array [1..4] of TPoint; //Added, Control Points array.
begin
GetMousePos(sx, sy);
Dist:= Distance(sx, sy, ex, ey);
CtrlPoints[1]:= Point(sx, sy);
CtrlPoints[2]:= CtrlP1;
CtrlPoints[3]:= CtrlP2;
CtrlPoints[4]:= Point(ex, ey);
theta_inc:= 1.0 div Dist;
theta:= 0.0;
repeat
theta_Inc:= MinE(1.0 - theta, theta_Inc); //This is the line to stop theta over 1.0
theta:= theta + theta_Inc;
until(Theta >= 1.0);
result[High(result)]:= Point(ex, ey); //This is a failsafe. High = Length - 1.
end;




Now, we will just add the point-adding into this function and wrap it up :D



function PointOnCubicBezier(cp: TPointArray; t: Extended): TPoint;
var
ax, ay, bx, by, cx, cy,
tSquared, tCubed, Curve: Extended;
i: integer;
begin
Curve:= 3.0; //average curve.
cx := Curve * (cp[1].x - cp[0].x);
bx := Curve * (cp[2].x - cp[1].x) - cx;
ax := cp[3].x - cp[0].x - cx - bx;

cy := Curve * (cp[1].y - cp[0].y);
by := Curve * (cp[2].y - cp[1].y) - cy;
ay := cp[3].y - cp[0].y - cy - by;

tSquared := t * t;
tCubed := tSquared * t;

result.x := Round((ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x);
result.y := Round((ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y);
end;


function Spline(ex, ey: integer; CTRLP1, CTRLP2: TPoint): TPointArray;
var
theta, theta_Inc: extended; sx, sy: integer;
Dist: integer;
CtrlPoints: Array [1..4] of TPoint; //Added, Control Points array.
begin
GetMousePos(sx, sy);
Dist:= Distance(sx, sy, ex, ey);
CtrlPoints[1]:= Point(sx, sy);
CtrlPoints[2]:= CtrlP1;
CtrlPoints[3]:= CtrlP2;
CtrlPoints[4]:= Point(ex, ey);
theta_inc:= 1.0 div Dist;
theta:= 0.0;
repeat
theta_Inc:= MinE(1.0 - theta, theta_Inc); //This is the line to stop theta over 1.0
theta:= theta + theta_Inc;
SetLength(Result,Length(Result)+1);
Result[High(result)]:= PointOnCubicBezier(ctrlpoints, theta);
until(Theta >= 1.0);
result[High(result)]:= Point(ex, ey); //This is a failsafe. High = Length - 1.
end;




now, to execute this spline path, just make a function like so. This will simply move your mouse path.


procedure MoveTheMouse(x, y, rx, ry: integer);
var
P: TPointArray;
I: integer;
begin
x:= x+random(rx);
y:= y+random(ry);
P:= Spline(x, y, {CTRLP1}, {CTRLP2});
for i:= 0 to High(P) do
begin
MoveMouse(P[i].x, P[i].y);
wait(randomrange(4, 8));
end;
end;
.






Adding Wind

Adding wind is simple. You can do a calculated version or a failsafe version. We will not discuss the calculated version, since you could make some math mistakes and it would take longer, but the failsafe, where you do almost no math and you cannot fail :D. Lets get our magic line again :D:



theta_Inc:= MinE(1.0 - theta, theta_Inc);


Simply add a wind variable into your parameters and replace the magic line with this code.



theta_inc:= theta_inc + wind;
theta_Inc:= MinE(1.0 - theta, theta_Inc);


You can play around with these variables to have a little fun :D.




Some Theta Tricks

ok, now there are some things you can do with theta that are actually pretty cool. This is what I was talking about when I said starting at a higher theta. Now, remember that line where we said


theta:= 0.0


well, you can change it to this



theta:= 0.3;


Let me explain what this will do, since it is hard to make a picture for it. Look at the first picture with the green spline path. Image the first blue control point marked 0.3 theta. Now, if you start this repeating equation with theta at 0.3, it will start the curve there on the line and it will "skip over" theta 0.0-0.2. You will still end up at end X and end Y, but you will start with a different curve other than this very strict line. You could also try something like



case random(4) of
0: theta := 0.2;
1: theta:= 0.122;
//etc..




For more information:
Wikipedia (http://en.wikipedia.org/wiki/B%C3%A9zier_curve)

Bobarkinator
11-21-2007, 02:29 AM
Thank you very much for this :). I will probably read it a couple more times through.

Smartzkid
11-21-2007, 02:33 AM
Wow, awesome!

Now maybe I can get that special object-finder mouse I wanted to make to work!

Town
11-21-2007, 03:05 AM
Great tutorial.

tarajunky
11-21-2007, 05:48 AM
This is the kind I want to be able to draw. :)

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

Find multiple points, save them to an array, then move your mouse through all of them on a smooth curve until you find the correct object.

HyperSecret
11-21-2007, 06:09 AM
looks very nice understood mostly all of the tut, the only thing i dont understand you have

curve := 3.0;

could someone explain alittle more what the curve means?, like what will happen if i increase or decrease the curve value?

pwnaz0r
11-21-2007, 06:23 AM
experement with it :)

mastaraymond
11-21-2007, 02:15 PM
Looks cool, nice job! Finally a new advanced tut :).

Btw, i was looking at a Spiral 'curve'. http://en.wikipedia.org/wiki/Archimedean_spiral thought it was kinda cool to make a mouse that moves like this :p. Im gonna give it a try ;).

Dumpin
11-21-2007, 02:51 PM
awsome =D thanks

nielsie95
11-21-2007, 03:16 PM
Nice, well explained :)
I actually created a MouseFunction some time ago using this (link (http://www.srl-forums.com/forum/beziermouse-t13392.html?t=13392)) :)


This is the kind I want to be able to draw. :)

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

Find multiple points, save them to an array, then move your mouse through all of them on a smooth curve until you find the correct object.

http://img140.imageshack.us/img140/6853/cardinalsplinejz3.jpg
Like this? :garfield:


Looks cool, nice job! Finally a new advanced tut :).

Btw, i was looking at a Spiral 'curve'. http://en.wikipedia.org/wiki/Archimedean_spiral thought it was kinda cool to make a mouse that moves like this :p. Im gonna give it a try ;).

function ArchimedeanSpiral(StartX, StartY, Size: Integer; Curve, StepSize: Extended): TPointArray;
var
t, x, y: Extended;
Count: Integer;
begin
repeat
t := t + Abs(StepSize);
begin
x := Size * (Curve * t) * cos(t) + StartX;
y := Size * (Curve * t) * sin(t) + StartY;
SetArrayLength(Result, Count + 1);
Result[Count] := Point(Round(x), Round(y));
Inc(Count);
end;
until t >= Size + (4 * pi);
end;

tarajunky
11-21-2007, 05:26 PM
[QUOTE=nielsie95;276203]Nice, well explained :)
I actually created a MouseFunction some time ago using this (link (http://www.srl-forums.com/forum/beziermouse-t13392.html?t=13392)) :)



http://img140.imageshack.us/img140/6853/cardinalsplinejz3.jpg
Like this? :garfield:

Yes, how did you do that?

the scar noob
11-21-2007, 08:59 PM
thanks for making the tut pwnaz0r ^,^

Like I've promised through msn, I'll look closer to it tomorrow, I'm actually very busy atm:)

Regards,

-Tsn.

pwnaz0r
11-22-2007, 01:41 AM
Alright :D

Infantry001
11-22-2007, 03:00 AM
thanks for the tut! itll be great to learn off of :D

R0b0t1
11-23-2007, 04:44 PM
Its not really the same when you copy all of the code from Wikipedia. :\


But this hath given me Ideas.

R0b0t1
11-23-2007, 09:18 PM
What-the-hell is up your ass? I happened to read the Wikipedia article and saw that they had some C code for it. It looked like you just ported it to SCAR/Delphi and released it in this tutorial. I'll post it below: It has the same variable names and method names as when I read this tutorial.

http://en.wikipedia.org/wiki/B%C3%A9zier_curve#Code_example


I really don't know what copying code has to do with citing Wikipedia and its pictures (as I do in my tutorials). They also state that you can use there resources as you please (I think they say you can't sell it though). I'm not saying that you shouldn't have copied the code, but you should have added more of you to it instead of doing (what is in my opinion) just rewriting the articles.


I really don't understand why you insist on attacking me for stating an opinion.

R0b0t1
11-23-2007, 09:41 PM
I'm not posting shit. I'm posting my opinions, ideas, and personal statements.


And you still didn't see what I said, I said that I saw code with the same variable names and the same method names on Wikipedia. It led me to believe that you had read or copied and translated the code to SCAR/Delphi.

I think this problem started a while back when we got in a fight. Ever since, you've been seeing what you've wanted to see, which is me trying trying to attack your work. You should try to stop seeing it with me as the attacker every single time.

Smartzkid
11-23-2007, 10:00 PM
Guys, shame on you. Calm down and start acting mature.

Pwnaz0r: he didn't give it very nicely, but all he was trying to do was give you some constructive criticism.

Robot: try not to accuse people when you're trying to help them.

pwnaz0r
11-23-2007, 10:09 PM
Whatever, im done with it.

please learn not to critise other peoples work, especially mine which I take great pride in and put tons of time into writing and constructing. You did not give me constructive critiscm, you tried to insult my tutorial in some random way that I did not even come close to doing.

R0b0t1
11-23-2007, 10:58 PM
Ok, I extend my love to you. :)

Timothegreat
12-23-2007, 12:02 AM
http://www.cs.technion.ac.il/~cs234326/projects/fonts/Methods.htm

This page describes control points and the adaptive bezier. And btw, using your tutorial i have created my own mouse. Thanks :D

pwnaz0r
12-24-2007, 05:15 PM
Welcome :D

hackncrack1
05-25-2009, 02:25 PM
could some plz put up an example to complete my understanding of how this works

Da 0wner
05-25-2009, 04:37 PM
Why you gravedig :'(.

And look in Mouse.scar :D.

hackncrack1
05-25-2009, 07:13 PM
i have looked in mouse.scar, but nothing there looks like this

ZephyrsFury
05-25-2009, 07:46 PM
WindMouse by BenLand100 creates the mouse path used in SRL mouse functions. Its rather different to this though.

Dervish
05-30-2009, 03:31 AM
why you gravedig :'(.

And look in mouse.scar :d.

no such thing as gravedigging for tutz ! :o

Dark Arcana
05-30-2009, 06:12 PM
no such thing as gravedigging for tutz ! :o

Exept when they are outdated.

MylesMadness
06-07-2009, 09:11 PM
Exept when they are outdated.No, not even then. Stop the backseat modding

Da 0wner
06-07-2009, 09:20 PM
This still is a great tutorial and is not outdated...

Also, Dark Arcana, I know you are just trying to get cups like SRL Helper...+1 to what myles said.