Jump to content
  • Advertisement
Sign in to follow this  
Kibble

Putting a tension into hermite splines

This topic is 4807 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I need to put a tension value into hermite splines, any idea of how to do this? My problem is I'm trying to move RTS units in such a way that the leave their position in the direction they face, turn to their destination, and arrive at the needed orientation, all in one motion. Right now they just spin in place when necessary, it is crappy. Because of this I need a spline that takes two points and the tangents. So either a way to introduce a tension variable into hermite splines, or another type of spline that suits that criteria would be helpful.

Share this post


Link to post
Share on other sites
Advertisement
This should do what you want:

inline void Vector::hermite( const Vector& from, const Vector& to, const Vector& startdir, const Vector& enddir, float factor )
{
float f2 = factor * factor;
float f3 = f2 * factor;
float p1 = 2.0f * f3 - 3.0f * f2 + 1.0f;
float p2 = -2.0f * f3 + 3.0f * f2;
float p3 = f3 - 2.0f * f2 + factor;
float p4 = f3 - f2;

x = from.x * p1 + to.x * p2 + startdir.x * p3 + enddir.x * p4;
y = from.y * p1 + to.y * p2 + startdir.y * p3 + enddir.y * p4;
z = from.z * p1 + to.z * p2 + startdir.z * p3 + enddir.z * p4;
}



This is the code for a hermite curve, which could be used for your units movement.

Share this post


Link to post
Share on other sites
Right, I've got that already. What I need is to figure out how to put a tension in there, so large units make wider turns than small ones. Changing the length of the tangent vectors will change the distribution of points on the spline, will it not? What I really need to do is make the code more robust so it doesn't go crazy when I test things like that for myself. Is this the answer though, or do I need some other stuff to use in the calculation?

Share this post


Link to post
Share on other sites
I've given up on using hermite splines or any other type of splines for this. At first it sounded good and easy, but it is a really crappy method. I need to figure out some other method of directing units in a smooth path without turning in place. Does anyone have any ideas for this?

Share this post


Link to post
Share on other sites
Why can't you just turn the unit x*dt degrees towards the target direction each frame? The lower the x-value is, the wider the turn will be.

Share this post


Link to post
Share on other sites
Of course, but that requires turning in place at the destination to reach the destination direction.

I will explain my problem more: There are a few units that are massive (they aren't constructed at a building, you build them as if it was a building, then when it is done you can use it like a unit). It is necessary to be able to have them facing a certain direction when they arrive at a destination, so they can start shooting quickly. Lets say you wanted to place 2 of these on the edge of your base to defend it, they turn very slowly, so you need to tell them what direction to point so when an enemy unit shows up its facing mostly the right direction. Here is some ascii art (the line shows what direction the unit is facing). Here is what it would do now:


Start
+---
\ .
\ .
\ .
\ .
\ .
\ .
\ .
\ .
\ .
\ .
\ .
\ .
+
/ Destination
/

Here is what I want it to look like:


Start
+---
--
\ .
\ .
\ .
\ .
\ .
\ .
\ .
\ .
\ .
|
/
+
/ Destination
/

The picture is crap but hopefully you get the idea. This way, the unit would arrive at the destination in the right direction. Hermite splines fit this well because you just use the start and destination as the two points, and the directions as the tangents. Splines are a bad solution though because they are inflexible, and I have to keep where the unit started from.

I think it is a similar problem of having an airplane take a path so it is lined up with the runway as it lands. The analogy to my current solution would be having the plane go to the start of the approach to the run way in a straight line from its current position, stop in midair, turn to face the runway, then land. I want it all in one smooth motion.

What I need is a routine or function that takes 5 arguments: start position, start direction, destination position, destination direction, and dt. The routine needs to provide the heading and speed for this frame to eventually arrive at the desired destination and direction.

I dont have a proper physics system, so just something that looks good and moves at a certain speed and turning radius (depending on the size of the unit) is fine.

edit: Backslashes are really screwed up.

Share this post


Link to post
Share on other sites
There is a paper called "Interpolating Splines with Local Tension, Continuity and Bias Control" which explains pretty straight forward how to add tension to a spline in a very simple way. I've used it myself and it's not perfect but it will probably work ok for most purposes. I think it's the same as Kochanek-Bartels splines.

Share this post


Link to post
Share on other sites
I thought this up a few hours ago.. just didn't have time to write it down for you as I've been at the bathhouse all day =)

well here it goes... untested and probably not bugfree =p (haven't even tryed to compile it myself)


// move() - returns the new direction of the unit
// position - units current position
// direction - unit vector front vector of unit
// targetpos - target position
// targetdir - target direction (unit vector)
Vector move ( Vector position, Vector direction, Vector targetpos, Vector targetdir )
{
Vector dpos = targetpos - position;

// angle to targetpos
float d = dot(direction, dpos);

// targetpos is infront of unit
if ( d >= 0 )
{
// angle to targetdir
d = dot(direction, targetdir);

// targetdir is within 90 deg of diretion
if ( d >= 0 )
{
// a vertical plane created from three points (assumes z-axis up)
Plane plane(position, targetpos, targetpos + Vector(0,0,1));
plane.d = 0; // needs to go through origo

// mirror the unit vector targetdir against the plane
d = plane.distance(targetdir);
return targetdir + plane.normal * -d;
}
// targetdir is more than 90 deg of direction
else
{
// just invert targetdir to get the units new dir
return targetdir.inverted();
}
}
// targetpos is behind unit
else
{
// turn unit x degrees the shortest way towards targetpos
Vector rotdir; // do some simple trig-magic here =)
return rotdir;
}
}





This is how I would move my units in a RTS. The func move() should be used to get the new direction of a unit when it is at a certain distance(²) from the targetpos. If it is used when the unit is too far away from its targetpos then it might start to align to targetdir to soon, and that will cause it to take a VERY wide turn.

I will try to compile this later on today to see how it works. Let me know if you want help with the "trig-magic" =)

[edit] note that this only gives a direction in the xy plane and doesn't take into account differences in height(z).

[edit 2] You also need to check if targetpos is reached or surpassed. To assure unit has aligned properly to targetdir just put direction equal to targetdir when it is at its target position

[Edited by - glSmurf on June 19, 2005 11:45:19 AM]

Share this post


Link to post
Share on other sites
The problem with that is that it only will work horizontally. While I don't need it to work in all 3 axes correctly, the game is underwater and all the units are submarines, so it would be good to have. It seems to me that there should be a relatively nice solution to this.

One idea that I had was to go back to the spline idea but instead of storing where and what direction the unit started from, just make a spline for the current position and direction, and the target position and direction. Then use the standard rotate x amount toward the target idea, toward the middle (parameter wise, ie t = 0.5) of the spline. If I play this out a few steps in my mind it seems to work except for when the unit is very close to the target, in which case I'm going to use turning in place anyways regardless of what method I come up with for this. I think it will work because while the unit is turning around if necessary, the point will force it in that direction, and once it is moving toward the destination the middle of the spline should still push the unit out in such a way that causes it to arrive at the target direction. If I can figure out a way to hack the max turning radius into this, I think it will work well (I think if I just use a low rotate x amount per frame large units could overshoot the target).

This should also be a lot better than my crappy implementation I was using before, which partly involved numerical integration to find the distance along the spline. I think that is why changing the length of the tangents was so unreliable.

edit: Didn't catch your edits, I agree.

Also, it always will turn in place at the destination if necessary, all I'm trying to do is make it so it arrives that way when possible.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Go for TCB splines, which are basically hermite splines, but with the tangents calculated on a way which allow you to set a tension, continuity and bias value per control point.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!