Hi Casey,
The rotation problem has been finally solved. Thank you so much for all your help.
Inspired by you, I changed the algorithm for creating the rope a little bit. Instead of always rotating and translating from the base circle to those positions on the central line, now we only do it for the starting circle, but for the rest of circles, each one is based on its previous circle on the central line: rotating and translating from its previous circle. By doing so, we actually avoid the need to handle the complaxity of a lot of different cases. E.g., whenever the rope goes upwards first then goes downwards, or goes forwards first then goes backwards, it has to be ended up with doing:
rotationAngle = -(float)Math.Acos(Vector3.Dot(rotationAxis, Vector3.Up));
rotationAngle += MathHelper.Pi;
This is because the Math.Acos returns an angle always smaller than a Pi. But the rope has some cases needing the rotation bigger than Pi, otherwise a crossover (over-rotated ones) would happen, and it's very hard to cover and handle all the cases.
The new algorithm can help avoid this complexity, because the angle between previous cirle base axis and the current circle base axis will never be bigger than a Pi. Hence the problem is solved by doing this:
//get the current circle's base axis
rotationAxis = Vector3.Normalize(calVectors[i + 1] - calVectors[i]);
rotationAxis = Vector3.Normalize(calVectors[i + 1] - calVectors[i]);
//angle between circle's base axis and previous circle's base axis
rotationAngle = -(float)Math.Acos(Vector3.Dot(rotationAxis, previousAxis));
rotationAngle = -(float)Math.Acos(Vector3.Dot(rotationAxis, previousAxis));
//find a vector perpendicular to both the circle's base axis and the circle's base axis
rotationAxis = Vector3.Cross(rotationAxis, previousAxis);
rotationAxis.Normalize();
rotationAxis = Vector3.Cross(rotationAxis, previousAxis);
rotationAxis.Normalize();
//save current circle's base axis for next run
previousAxis = Vector3.Normalize(calVectors[i + 1] - calVectors[i]);
previousAxis = Vector3.Normalize(calVectors[i + 1] - calVectors[i]);
//construct the rotation matrix from the rotation axis and rotation angle
rotationMatrix = Matrix.CreateFromAxisAngle(rotationAxis, rotationAngle);
magicMatrix = Matrix.CreateTranslation(-calVectors[i - 1]) * rotationMatrix * Matrix.CreateTranslation(calVectors[i]);
rotationMatrix = Matrix.CreateFromAxisAngle(rotationAxis, rotationAngle);
magicMatrix = Matrix.CreateTranslation(-calVectors[i - 1]) * rotationMatrix * Matrix.CreateTranslation(calVectors[i]);
newCircle = new Vector3[baseCircle.segPointNo];
//transform from the previous to current one
Vector3.Transform(vectorCircleList[i - 1].vecotrCircle, ref magicMatrix, newCircle);
vectorCircleList.Add(newCircle);
With this new algorithm, we finally got this very nice rope:
No comments:
Post a Comment