the path is consist of several points: ABCDEFG....etc
and I've succeeded letting the scenenode move on the path, but, don't know how to rotate the scenenode and make its animating direction follow the path, which means...... the locomotive always faces the front it goes.
and irrlicht only provide setRotation(core::vector3df vec) to set the rotation, so i must calc the rotation of each axis first....
I wonder anyone who can give some help on the calculations?
make a followpath animator
i would do an interpolation like the following:
it would interpolate between way point 1's predefined rotation and waypoint 2's predefined rotation, the interpolation ratio / factor would be the distance from waypoint one.
This would be performed on the x value y and z values of the nodes rotation every frame
it would interpolate between way point 1's predefined rotation and waypoint 2's predefined rotation, the interpolation ratio / factor would be the distance from waypoint one.
This would be performed on the x value y and z values of the nodes rotation every frame
If you had a quaternion or rotation matrix for every point on the spline path, that would be a possible solution. Normally the spline path only has points and those points don't have orientations.
The existing spline path code does figure out the tangents of the points that are being interpolated across. You could use these to get rotation matrices or quaternions and then lerp those.
Travis
The existing spline path code does figure out the tangents of the points that are being interpolated across. You could use these to get rotation matrices or quaternions and then lerp those.
Travis
-
michael520
- Posts: 230
- Joined: Mon Oct 10, 2005 2:24 am
from the source code, we could see that the follow spline animator doesn't do rotations! it only animates the node's position.
what I want is not spline, it's line segments: ABCDEF...., with corners not smooth.
the position is easy to calculate, which is based on time ticks with constant speed.
the rotation, for example, on segment AB, the truck should face the direction normalized vectorAB=vectorB-vectorA;
and I predefine that on init, the truck is facing axis Z+ direction, and axis Y is its upper direction. so, when the truck turn left or right, the truck should do rotations on axis Y. and I also predefine that the truck's local X axis is always parallel to horizontal plane. so, when the truck goes on a brae, it would do rotations on its local X axis.
and the following is what I do:
what I want is not spline, it's line segments: ABCDEF...., with corners not smooth.
the position is easy to calculate, which is based on time ticks with constant speed.
the rotation, for example, on segment AB, the truck should face the direction normalized vectorAB=vectorB-vectorA;
and I predefine that on init, the truck is facing axis Z+ direction, and axis Y is its upper direction. so, when the truck turn left or right, the truck should do rotations on axis Y. and I also predefine that the truck's local X axis is always parallel to horizontal plane. so, when the truck goes on a brae, it would do rotations on its local X axis.
and the following is what I do:
Code: Select all
CSceneNodeAnimatorFollowPath::CSceneNodeAnimatorFollowPath(core::array<core::vector3df> arrPath,
float fSpeed, u32 now)
{
path = arrPath;
speed = fSpeed/1000;
timeStart = now;
pathLength = 0;
pathTicks.push_back(0);
for(int i=0;i<arrPath.size()-1;i++)
{
pathLength += (arrPath[i+1]-arrPath[i]).getLength();
pathLengths.push_back(pathLength);
pathTicks.push_back(pathLength/speed);
if(i<arrPath.size()-1)
{
core::vector3df vec = arrPath[i+1] - arrPath[i];
vec.normalize();
pathVectors.push_back(vec);
}
}
pathTime = pathLength/speed;
}
CSceneNodeAnimatorFollowPath::~CSceneNodeAnimatorFollowPath(void)
{
}
void CSceneNodeAnimatorFollowPath::animateNode(ISceneNode* node, u32 timeMs)
{
u32 t = (timeMs - timeStart)%pathTime;
core::vector3df pos;
int i=0;
bool b = false;
if(t==0)
pos = path[0];
else if(t>=pathTime)
{
pos = path.getLast();
}
else
{
for(i=0; i<pathTicks.size()-1; i++)
{
u32 tick=pathTicks[i];
if(t>pathTicks[i] && t<pathTicks[i+1])
{
pos = path[i] + pathVectors[i] * (t-pathTicks[i]) * speed;
b = true;
break;
}
}
}
//do rotation:
float sqrt2 = 0.7071067812; //sqrt(2)
if(b)
{
float x=pathVectors[i].X;
float y=pathVectors[i].Y;
float z=pathVectors[i].Z;
float rotY=0;
float rotX=0;
float rotZ=0;
if(y==0)
{
rotX=0;
}
else
{
float xz=x*x+z*z;
rotX=acos(sqrt(xz/(xz+y*y)))*180/core::PI;
if(y>0)rotX *= -1.0f;
}
if(x*x+z*z==0)
{
if(y>0)
rotY=90;
else
rotY=-90;
}
else
{
rotY=acos(z/sqrt(x*x+z*z))*180/core::PI;
if(x<0)rotY *= -1.0f;
}
node->setRotation(core::vector3df(rotX,rotY,0));
}
node->setPosition(pos);
}
-
michael520
- Posts: 230
- Joined: Mon Oct 10, 2005 2:24 am
the above code, which I have tested, works fine in most cases. it only does rotations on axis X and Y. Scene node will be animates correctly and always face the directions it's following. It will be enough for cars and trucks which are moving on the ground.
But when I test deeper, I found that it's not perfect on some cases, such as for airplane flight, whose rotations will be on three axis X, Y, and Z.
I think, on these cases, we have to define more on the path, not only positions of the way points, but also something else such as upper directions...
So I wonder if anybody has done some study on these cases, and share some ideas?
But when I test deeper, I found that it's not perfect on some cases, such as for airplane flight, whose rotations will be on three axis X, Y, and Z.
I think, on these cases, we have to define more on the path, not only positions of the way points, but also something else such as upper directions...
So I wonder if anybody has done some study on these cases, and share some ideas?