I have been trying to figure out how to get the perpendicular to a normal vector so that I can draw the body of a worm. Not sure if I am doing this in the best way, so any feedback or suggestions would be great.
This is how the worm is supposed to look.
[attachment=1:6z4twkwc]Picture 4.png[/attachment:6z4twkwc]
But when I begin moving the worm around, it looks like this:
[attachment=0:6z4twkwc]Picture 2.png[/attachment:6z4twkwc]
i might be misunderstanding - but be careful here.
in 3d there isnāt really such a thing as a perpendicular vector to another vector. instead, a normal is only perpendicular to a plane. once you have the plane you can do 2d translations on that. but thereās no such thing as a vector perpendicular to another vector in 3d.
This works well,except there seems to be a bit of snapping of rotation at certain points, along the spine. So this works for the circles around the spine, but as far as creating a skin or drawing polygons or triangles, it may function a little quirky.
Now it looks like this, there is no checking if the body is folding on itself right now.
[attachment=0:3vxyy1d3]Picture 5.png[/attachment:3vxyy1d3]
could you be a little bit more specific about what the problem is exactly? i can see the worm in the first picture, then in the second the same worm that looks also to be drawn fine, assuming the twisting line of black dots is supposed to be the spine of the worm⦠just not sure whatās wrong, nor how you want to fix it.
This is hard to explain without seeing the animation, but hopefully this picture will clear it up. Some of the body segments get twisted and do not line up with the others, this may just be the drawing of triangles. In this example, it is just running through the array and connecting the points based on the index in the array. I will try finding the nearest point in the next segment, but that will slow down processing and it only seems to happen when the segments are aligned along the up axis, as display in the picture.
right - iām guessing this is because of the way youāre calculating the āperpendicularā vector to the worm spine.
you need to somehow define an up vector for the entire worm that is independent of the camera up vector, and then use that to make sure your point creation is always starting from the same position āaboveā the spine - does that make sense?
What you are after is something called the Parallel Transport Frame, or just Parallel Transport sometimes.
You can find some info here to get you started: http://en.wikipedia.org/wiki/Parallel-transport
If you happen to have access to Game Programming Gems 2, there is a pretty good explanation of it
in there, otherwise just google around and you will end up in a bunch of physics/math/game dev forum threads
discussing it.
Damian, I have tried to get the up vector for the worm, but the twisting occurs even more. The problem seems to occur when the axis (spine vector) aligns with the up vector. Not sure if I was doing it correctly, but I tried several methods.
[quote author=āedvinbesicā]What you are after is something called the Parallel Transport Frame, or just Parallel Transport sometimes.
You can find some info here to get you started: http://en.wikipedia.org/wiki/Parallel-transport
Edvin[/quote]
Edvin, I have read a couple of articles on this subject, however, I am uncertain how to apply it to the issue that I am having. The book you recommended was on Google Books, but the part on Parallel Transform was left out.
I understand that it rotates a vector based on a sphere, but not sure how it applies to the rotation around an arbitrary axis. This is the code that I am using to calculate the points around the spine, where dirNormal is the spine normal and up is the camera up (0, 1, 0);
I set the initial point of the worm to influence the up vector of the worm for the rest of the tube that I used parallel transport on.
Based on this info from Craig Reynolds, http://red3d.com/cwr/steer/gdc99/index.html,
I set the approximate up vector to the up vector of the previous frame and the forward vector to the direction normal. Then I set the side vector to the cross of the forward and approximate up vector. Then set the new up to the cross of the forward and the side vector.
Based on the awesome Game Programming Gems 2 book recommended by Edvin,
I performed parallel transport on the rest of the body points to extrude along the path and it solved the problem.
This is located inside the worm update loop, where the spine vector is a list of points that compose the middle of the worm. For the first spine point, I used the Craig Reynolds method for storing and estimating the up vector. And for the rest, the parallel transport method, mentioned by Edvin in a previous post, based on the previous spine pointās orientation, since it lined up the points better.
This could probably be optimized, but it works for now.
Hope this helps
if (i == 0) {
// dirNormal is a normalized vector between spine points //
// Reynolds Method [url][http://red3d.com/cwr/steer/gdc99/index.html[/url]](http://red3d.com/cwr/steer/gdc99/index.html[/url])
ofxVec3f new_forward(dirNormal.x, dirNormal.y, dirNormal.z);
new_forward.normalize();
ofxVec3f approx_up(-spine[i].orientation.up.x, -spine[i].orientation.up.y, -spine[i].orientation.up.z);
approx_up.normalize();
ofxVec3f new_side = new_forward.crossed(approx_up);
ofxVec3f new_up = new_forward.crossed(new_side);
new_up.normalize(); // just in case
spine[i].orientation.up.set(new_up.x, new_up.y, new_up.z);
spine[i].orientation.forward.set(new_forward.x, new_forward.y, new_forward.z);
spine[i].orientation.side.set(new_side.x, new_side.y, new_side.z);
//////////////////////////////////////////////////////////////////////////////
} else if (i < numBodyPts) {
// Game Programming Jems 2 Approach ////////////////////////////////
ofxVec3f T1(spine[i-1].loc.x, spine[i-1].loc.y, spine[i-1].loc.z);
ofxVec3f T2(spine[i].loc.x, spine[i].loc.y, spine[i].loc.z);
ofxVec3f A = T1.crossed(T2);
float alpha = T1.angleRad(T2);
ofxVec3f new_forward(dirNormal.x, dirNormal.y, dirNormal.z);
ofxVec3f approx_up(-spine[i-1].orientation.up.x, -spine[i-1].orientation.up.y, -spine[i-1].orientation.up.z);
approx_up.normalize();
approx_up.rotateRad(alpha, A);
ofxVec3f new_side = new_forward.crossed(approx_up);
ofxVec3f new_up = new_forward.crossed(new_side);
spine[i].orientation.up.set(new_up.x, new_up.y, new_up.z);
spine[i].orientation.forward.set(new_forward.x, new_forward.y, new_forward.z);
spine[i].orientation.side.set(new_side.x, new_side.y, new_side.z);
}
when it is time to draw the tubes, you can loop through and get the cross vector from the forward and up vectors.
After comparing some code and reading the PTF paper this is my implementation, which seems to give me a perfect result, but Iām still not totally sure as the gab between the maths used and which were given in the paper is huge