Hello 
I'm Siobhan Curran/Kisa Naumova, and this is my weblog. I tend to write about stuff like crossdressing, Macs, code, cats, wine and Second Life, but in general it's just an ongoing conversation about all sorts of stuff. If you'd like to know a little bit more about what this all is, I recommend starting on this page which has a little bit of info on who I am, and what I'm trying to do — or you could dive into my five years worth of archives if you like.
Otherwise, feel free to close this box and explore...
Prim Tweening (Revisited)
Just going back to the thing I was talking about the other day, of trying to join the gap between two prims smoothly, you may recall that although what I came up with worked, it was rather inelegant (to say the least). Simply interpolating the steps from one to the other used far too many prims, all of which overlapped, and took a straight-line path. For the past week though, I've been wondering if I could plot a three-dimensional bezier curve between them instead, and I finally got around to trying it out this morning.
OK, so what I'm starting out with here is two prims and a couple of control points.
Something to note about the two main prims, is that their Y faces are pointing towards each other — ie. those are the faces I'm going to join up. At some point, I'm hoping to develop this into a completely automatic script that won't need such careful planning (along with extrapolating the control points without having to plot them out manually) — but for now, this is just a bit of a 'rapid prototype' ![]()
The control points in this case then, I made by setting my grid option to 'Local', and shift dragging each of the two prims out to what looked like a sensible position.
OK, now the maths...
$x = array(91.244,92.663,92.844,93.495) ;
$y = array(232.031,230.426,227.556,224.657) ;
$z = array(501.534,502.764,503.783,504.354) ;
The first step (just to make my life easier) is to put the positions into some handy arrays. The order of the co-ordinates above is start, control-1, control-2, end.
Then I set out some variables...
$steps = 20 ;
$increment = 1 / $steps ;
...and apply the bezier equations I got from here to each of the three dimensions...
for($i=0, $t=0;$t<=$steps;$i+=$increment, $t++) {
$cx = 3 * ($x[1] — $x[0]) ;
$bx = 3 * ($x[2] — $x[1]) — $cx ;
$ax = $x[3] — $x[0] — $cx — $bx ;
$pos[$t]['x'] = ($ax * pow($i,3)) + ($bx * pow($i,2)) \
+ ($cx * $i) + $x[0] ;
$cy = 3 * ($y[1] — $y[0]) ;
$by = 3 * ($y[2] — $y[1]) — $cy ;
$ay = $y[3] — $y[0] — $cy — $by ;
$pos[$t]['y'] = ($ay * pow($i,3)) + ($by * pow($i,2)) \
+ ($cy * $i) + $y[0] ;
$cz = 3 * ($z[1] — $z[0]) ;
$bz = 3 * ($z[2] — $z[1]) — $cz ;
$az = $z[3] — $z[0] — $cz — $bz ;
$pos[$t]['z'] = ($az * pow($i,3)) + ($bz * pow($i,2)) \
+ ($cz * $i) + $z[0] ;
}
...pulling all the results into a handy $pos array for later use.
With me? ![]()
Like I said, I've been planning this out in my head all week, unsure whether the two-dimensional sketches I've been making would match my mental three-dimensional gymnastics.
But it did ![]()
The next step was working out what sizes the intermediate prims needed to be, and how they needed to be rotated to get a smooth curve. Initially, things went completely to pot...
What I was trying to do there, was use the differences between two points to set the rotation. Initially, my code was something like this...
for($j=0,$k=1;$j<$steps;$j++,$k++) {
$dx = $pos[$k]['x'] — $pos[$j]['x'] ;
$dy = $pos[$k]['y'] — $pos[$j]['y'] ;
$dz = $pos[$k]['z'] — $pos[$j]['z'] ;
$rx = rad2deg(atan2($dz, $dy)) ;
$ry = rad2deg(atan2($dx, $dz)) ;
$rz = rad2deg(atan2($dx, $dy)) ;
}
The trouble with doing it that way, was that it doesn't take into account the rotation of the initial prims, so even though I was getting a smooth curve, it didn't join the gap properly.
So I resorted to the 'tweening' code that I wrote the other day, and that worked just fine² ![]()
All that was left was to work out the distance between each prim edges, and apply that to the Y-size...
$size = sqrt((pow($dz,2) + pow($dx,2) + pow($dy,2))) ;
Nice, but a little bit blocky. On a complete whim, I figured I'd see what happened when I twisted the prims ever so slightly...
Not bad, eh?
...
Now then. Obviously, this is no finished, polished script. My unfamiliarity with LSL means that for stuff like this, I'm much happier thrashing out the numbers in a PHP script — and this is no exception. Plus, as you can probably see from the snippet of code at the top, there's no slick interface for getting the initial values — I'm copy-pasting them directly from SL into the PHP.
What I would like to happen, is for to be able to just chuck a couple of scripts into existing prims, fire them up, and watch them do their stuff. But I'll need some help from more experienced LSL scripters for that¹.
Just a few thoughts though:
The control points should be able to be determined from taking the overall distance between the start and end points, dividing by three, and extending out from the Y-face of each. Although I might be wrong on that.
I think it does always have to be the Y-face that points in the direction you want, because otherwise twisting the prims to smooth them out a bit won't work.
Regarding the twisting, I've yet to work out what the relationship between the number of steps and the twist amount is. Just a casual glance at my notes says it's something like the sum of all the rotational differences divided by the number of steps, but that's just a guess on my part.
Also, SL only seems to let you twist things in multiples of 2. Which is a bit poo really.
And, I'd like to be able to taper the prims as well — to get them to fit perfectly — but I don't think I can taper and twist them the way that I want. Seems to be either one or the other.
Anyways. If anyone wants the code to have a nosey around, I've put a zip of it here.
The LSL part — the bit that rezzes the blocks and makes them go to the right place — is just a slightly modified version of my SVG rezzer. If you chuck me an IM, I'll send you a copy to play with.
¹ Hint hint.
² I spoke too soon. Trying it out on a much larger scale proved that interpolating the rotation just doesn't work properly. What I was saying earlier about "it doesn't take into account the rotation of the initial prims" is complete bollocks — the only reason it wasn't working properly is because my trigonometry is borked. If I can figure it out, it should work fine.
rachel
You might want to take a look at some A* (shortest path) algorithms. Wikipedia has some stuff on it: http://en.wikipedia.org/wiki/A*searchalgorithm
They might be able to help you figure out a path without the need to hard code anything. Besides, more complex paths might lead to some stunning results. (Something along the lines of let the A* figure out how to get there, and then apply the Bezier Curve calculations. More work, but less dependent upon prior knowledge. Let the computer do what it's good at: repetitive calculations.)
As I've only used the algorithm in Java and C++, I don't know if there's a PHP example out there.
Good luck with it! The results look really nice.
Carolyn Ann
Isn't A* used to find the shortest route in a node graph? In this case the shortest route would just be a straight line, like the first experiments.
/me nods
I'm starting to think, BTW, that just plotting out one curve between the centre of the two prims isn't enough to give me all the information I need to get the rotations right, and that I could get a lot more accurate a transition with four curves — between each of the corners of the opposing faces.
But I've got way too much ekse to do today. So that's one for the back burner I think.
Yeah, but not always. It can compute the shortest curve around a corner, for instance. A series of straight lines makes up the corner; which is what Siobhan is doing, anyway. I just thought it might be useful to reduce the amount of hard coded information.
The number of steps can be determined dynamically, and then you can also set intermediate points that might produce neat affects.
Ah well. Just brainstorming; sometimes those ideas are little of left field. And need to be discarded, but at least they're said. Forget I said anything. ![]()
(Sorry, couldn't resist.)
Carolyn Ann









Does this mean you didn't have to go and watch the Robbie Williams tribute act thingy this afternoon?