Drawing a long 3D tube #905

Closed
ashawthing opened this Issue Dec 14, 2011 · 85 comments

Projects

None yet

7 participants

@ashawthing

What is the easiest way to draw a long 3D tube that follows a 3D path.

I have a collection of 3D points that represent a route through my world and I want to highlight it. If I draw it as a THREE.Line it comes out 1 pixel wide which is impossible to see, so I want it as a 3D solid.

I tried extruding a shape along a path but that has a couple of issues - the path is defined in 2D and the shape (which is also 2D) doesn't rotate as it is extruded so I get thin points in my solid.

@mrdoob
Owner
mrdoob commented Dec 26, 2011

Oh... uhm...

@zz85: I guess the shape extrusion should tilt the shape every step in the direction the step is extruding?

@zz85
Contributor
zz85 commented Dec 28, 2011

right now extrudes only extrude perpendicularly only its z-axis, that's why only a 2d path is needed.

extruding with its angle adjust + via a 3d path is a feature that I hope to add sometime... (if i could finish my current demo first :S)

however, i think its possible to have a thick line with custom attributes. see http://alteredqualia.com/three/examples/webgl_custom_attributes_lines.html and #681

@tylorr
tylorr commented Mar 5, 2012

I would also really like this functionality. If is not implemented yet do you know of a simple-ish way of doing it by hand (custom vertices for a cylinder maybe)?

@zz85
Contributor
zz85 commented Mar 6, 2012

hmm.... I almost couldn't remember how ExtrudeGeometry's extrude path would work, so I wrote a simpler THREE.PathExtrudeGeometry with a SplineCurve3.

http://jsfiddle.net/bpSU3/

See if this extrusion works, I can probably tweak THREE.ExtrudeGeometry to work the same way.

@tylorr
tylorr commented Mar 6, 2012

This is great, but I also need its angle to adjust as it is extruded

EDIT: So would that involve at each step along path calculate rotationMatrix and then multiply each point in the shape by that matrix?

@zz85
Contributor
zz85 commented Mar 6, 2012

could you explain what is its angle adjusted as its is extruded, or are
there any examples?

@WestLangley
Collaborator

@zz85 The way to do this is to hack THREE.TorusKnotGeometry.

I think what @miningold is talking about is he wants each ring to be orthogonal to the tangent vector of the centerline.

One just needs to replace the getPos() function in TorusKnotGeometry.js. with a custom callback.

Well... then there is the issue of open vs. closed ends... and whether it is a closed or open path or not.... :-)

@tylorr
tylorr commented Mar 7, 2012

Wow, thanks, I didn't think about that, I'll give it a try.

My paths are going to be closed, and I think I can figure something out for the ends.

EDIT: My paths are going to start at some point A and end at some other point B... not sure if that is called closed or open.

@tylorr
tylorr commented Mar 7, 2012

Alright I am making some progress but I have run into two problems:

  1. I am getting a twisting effect if my path is bent at all
  2. If any point along my path is the zero vector then the tube collapses to a line

I don't have enough experience with trigonometry to identify what is causing these probelms. So help (and explanations) would be lovely.

Here is a link to what I have:
http://jsfiddle.net/miningold/L6wuG/5/

@WestLangley
Collaborator

Here is a fix, sort of. http://jsfiddle.net/L6wuG/6/ . This fix may prevent the twists.

This is a tricky problem, and it will take work to make it production quality, but perhaps it can work for your purposes.

Kinks will be a problem. A path that runs vertically will be a problem, too. Good luck. ;-)

@tylorr
tylorr commented Mar 7, 2012

This is awesome thanks.

I am ok with the kinks, but I definitely will need the path to run vertically. Do you have any suggestions for fixing this, or somewhere I could look (I don't know how to even phrase this for a google search).

EDIT:
So I figured out the problem has to do with the normal vector. So if the tangent vector is pointing straight up, should I set the normal vector to something like 1, 0, 0 or -1, 0, 0?

Another problem is when the tangent vector transitions from positive x-values to negative x-values (if z is unchanging). This causes the bitangent vector to point in the opposite direction. The problem is I don't know how to detect that in 3D space (when z is changing).

@WestLangley
Collaborator

Sorry, no other ideas at this point. I think your time is better spent understanding the 10 or so lines of code that calculate the variable pos, so you will understand what the problem is and why kinks and twists happen. It's just geometry.

At that point you will be in a better position to come up with a specific solution for your particular situation -- even if it doesn't work in the general case.

@tylorr
tylorr commented Mar 7, 2012

Alright, I've worked on it a bit more. I've gotten close, but every time I fix one edge case, another one appears.

Here is my progress:

http://jsfiddle.net/L6wuG/10/

The interesting thing is if I go back to setting the up vector to p1 + p2 then almost all of my problems disappear:

http://jsfiddle.net/L6wuG/12/

I've determined that the problem with up = p1 + p2 is when p1 and p2 form a straight line through the origin. This makes up and tangent equal, which then screws up the cross products.

@WestLangley
Collaborator

Yes, I know. But congratulations on your progress! I tried hacking something up myself, but no answers...

Setting up = p1 + p2 worked for the torus knot because it wraps around the origin and never passes through it.

If you are creating closed curves, can you restrict them to wrapping the origin and use the same trick?

@zz85
Contributor
zz85 commented Mar 7, 2012

okay, starting to understanding what you guys are saying :D

@miningold you can try THREE.ClosedSplineCurve3 for a closed tube :)

@tylorr
tylorr commented Mar 7, 2012

I am going to be using open curves, so I can't use that hack I guess

@zz85
Contributor
zz85 commented Mar 7, 2012

oh okay i understand, the "closed" here again refer to different things >.<

@tylorr
tylorr commented Mar 7, 2012

Alright to clear things up, I don't want my curve to loop. I want it to
have a start and an end.

@tylorr
tylorr commented Mar 8, 2012

So I found a good enough solution.

http://jsfiddle.net/L6wuG/18/

I am using up = p1 + p2, then I find the binormal (previously known as bitan). If the binormal is equal to the zero vector then I set the binormal to the previous binormal. It will cause a twist but it prevents the tube/pipe from collapsing.

@tylorr
tylorr commented Mar 8, 2012

Also, I discovered that this techniques is a slight variation of the Frenet–Serret formulas

@WestLangley
Collaborator

@miningold Your fiddle collapsed on me.

Here is a hack. http://jsfiddle.net/L6wuG/19/. It looks like it will work. It tries to prevent twisting by using the normal computed for the previous ring. Have a look. No guarantees, though.... Provided just in the interest of helping you... :-)

@tylorr
tylorr commented Mar 8, 2012

@WestLangley This is awesome, thanks. I would never have thought of it.

@zz85
Contributor
zz85 commented Mar 8, 2012

looks great! i've gotta learn about those FrenetSerret formulas sometime!

@tylorr
tylorr commented Mar 8, 2012

@WestLangley I believe the hack you provided will also break if p1 and p2 end up being parallel for the very first iteration.

@WestLangley
Collaborator

@miningold It was only proposed to get you through the night. It is not production quality.

@zz85
Contributor
zz85 commented Mar 9, 2012

finally i managed to wrap my head around those Frenet–Serret and TNB frame stuff!!

Its seems like all those twists are caused by some flipping of normals to the tangents of the cat-mull rom splines.

The solution, like what was done, uses the moving Frenet frame technique - pretty cool :)

I've modified the fiddle again, my approach is to use the derivative of the normalized tangent for the 1st iteration, then use the moving Frenet frame. I hope this works better.

http://jsfiddle.net/4NvBK/

@zz85
Contributor
zz85 commented Mar 9, 2012

Hmm, actually I'm not certain that solves the first iteration problem.

This version uses a arbitrary referencing binormal for the first iteration.

http://jsfiddle.net/mcvdx/

@zz85
Contributor
zz85 commented Mar 9, 2012

Seems like the referencing frenet frame method is also called the Rotation Minimizing Frames (RMF) :)

http://research.microsoft.com/en-us/um/people/yangliu/publication/computation%20of%20rotation%20minimizing%20frames.pdf

@WestLangley
Collaborator

@zz85 You are correct. This has been a long-standing problem.

Check out this: http://www.cs.cmu.edu/afs/andrew/scs/cs/15-462/web/old/asst2camera.html

It is the same concept I proposed in my hack #19, which seems to work, except for edge effects.

Here it is again: http://jsfiddle.net/EBtfS/

Maybe the CMU method will work better -- I havent't had time to investigate...

@zz85
Contributor
zz85 commented Mar 9, 2012

@WestLangley yes, the CMU's method is the one I used for my last 2 fiddles (oldB for the previous binormal:)
which is simpler (doesn't compute difference of tangent at current point and previous point)

Nice debugging arrows :) I was writing my helper arrow methods just now for investigating why frenet frame were so twisted too.

I think its more straight forward for a tube (as long N and B are perpendicular to T). It will be interesting once we add custom shapes for path extrusion.

@WestLangley
Collaborator

@zz85 Are you going to pursue this? I just don't have the time, currently... If so, I am interested in whatever you do.

Regarding the arrows, it would be nice to have an ArrowGeometry.

@zz85
Contributor
zz85 commented Mar 10, 2012

its on my TODO list, definitely hope to complete it when I have the time too, maybe sum it up with a procedural rollercoaster track :)

Maybe we can ask @mrdoob if he likes THREE.ArrowGeometry and THREE.TubeGeometry additions to three.js

@zz85
Contributor
zz85 commented Mar 10, 2012

having a little fun with THREE.Tube, THREE.Curve and some Math formulas :D

Heart
http://jsfiddle.net/rj9rE/1/

Viviani's Curve
http://jsfiddle.net/rj9rE/2/

Helix / Spring
http://jsfiddle.net/rj9rE/3/

Any other interesting formulas that come to mind? (Maybe a clothoids spiral)

@WestLangley
Collaborator

@zz85 Nice. I think we have the "spinning" issue resolved. The binormal seems to be well-behaved. http://jsfiddle.net/rj9rE/4/

However, the selection of a random initial binormal is a bit of a risk -- it is not guaranteed to work. Another option is to pick the one of (0,1,0), (1,0,0), or (0,0,1) that is most orthogonal to the intial tangent vector. To do that, identify the component of the tangent vector that has the smallest abs value, and select the unit vector that points in that component direction.

@WestLangley
Collaborator

@miningold not quite:

the smallest abs value

@tylorr
tylorr commented Mar 10, 2012

Oops forgot that part

http://jsfiddle.net/rj9rE/32/

Edit:

One more revision:
http://jsfiddle.net/rj9rE/33/

@mrdoob
Owner
mrdoob commented Mar 11, 2012

Maybe we can ask @mrdoob if he likes THREE.ArrowGeometry and THREE.TubeGeometry additions to three.js

Maybe it could be THREE.ArrowHelper? Something like THREE.AxisHelper?

@zz85
Contributor
zz85 commented Mar 14, 2012

I could try refactoring it to THREE.ArrowHelper. @WestLangley addArrow() pretty useful, I think it could also go into some util method or into ArrowHelper.addArrow()

@WestLangley
Collaborator

@zz85 addArrow() could be refractored to look like THREE.AxisHelper, so you'd do something like
scene.add( new THREE.ArrowHelper( .. ) ); . . . Please, be my guest. :-)

@zz85
Contributor
zz85 commented Mar 14, 2012

added THREE.ArrowHelper. zz85@d789954

I'm added an .orientate(dir) but not sure if it works after being initialized.

I also took a quick look at Matrix4.lookAt and its seem there's a hackish method to avoid 0 vectors by adding a 0.00001;
https://github.com/zz85/three.js/blob/master/src/core/Matrix4.js#L72 added (by @empaempa ?) which seems to work.

@WestLangley
Collaborator

@zz85 added THREE.ArrowHelper. I think setDirection( dir ) works properly now. Please have a look.

https://github.com/WestLangley/three.js/blob/dev/src/extras/helpers/ArrowHelper.js

Regarding Matrix4.lookAt(), I think it's about the best one can do to handle the edge effects.

@zz85
Contributor
zz85 commented Mar 15, 2012

@WestLangley
thanks. merged your changes and add a little tweaks THREE.ArrowHelper
zz85@d789954...c959a0c

i've also started to work on adding spline extrusions to THREE.ExtrudeGeometry too.

do you think THREE.TubeGeometry is stable enough to be included in three.js now?

@WestLangley
Collaborator

@zz85 hmm... I already submitted a pull request.

#1518

I am just learning how this git thing works, and I'm currently in a total state of confusion.... :/

Shoudl I cancel my pull request now... somehow?

Re: THREE.TubeGeometry, I think it is stable enough. Have a go.

@zz85
Contributor
zz85 commented Mar 15, 2012

@WestLangley
Perhaps you could try adding my fork as a remote and try merging my branch. My branch have includes ArrowHelper in the build script and couple of other changes.

git remote add zz85 https://github.com/zz85/three.js.git
git fetch zz85
git merge zz85/master

If our branches stay in sync, then both our changes will get merged whether mrdoob pull from your branch or mine.

@alteredq
Contributor

I can sort it out, just tell me which version of ArrowHelper should stay after the merge.

@WestLangley
Collaborator

@alteredq use @zz85's version. It has all my changes.

@alteredq
Contributor

So it's merged:

alteredq@685d72e

Please check if something didn't get messed up.

I also tried to clean up a bit this weird new extrude example, but it's still somehow strange.

@zz85
Contributor
zz85 commented Mar 16, 2012

@alteredq
i think the code merge looks fine. that extrude uv example is perhaps strange because it doesn't triangulate?

trying to debug it but haven't solve it yet.
[update] Its a triangulation error with the example. Fixed in my branch.

@zz85
Contributor
zz85 commented Mar 16, 2012

added TubeGeometry.js and examples.

zz85@cc6c1b5...f3fbacf

also started to work on path extruded geometry in https://github.com/zz85/three.js/tree/extrude_spline_rebasing

@alteredq
Contributor

[update] Its a triangulation error with the example. Fixed in my branch.

Nice ;).

I wonder why there are creases visible when antialiasing is turned on. There is something strange going on, even with basic material it appears as if there would be specular reflections.

Both these weird behaviors don't happen if material doesn't have texture.

@mrdoob
Owner
mrdoob commented Mar 16, 2012

added TubeGeometry.js and examples.

zz85@cc6c1b5...f3fbacf

So I guess we can remove TorusKnotGeometry.js or rework it to use TubeGeometry.js instead?

@zz85
Contributor
zz85 commented Mar 17, 2012

@mrdoob that's possible, although there's a little problem to solve with the last segment.

however, if done correctly, three.js could also become a knotting/graphing library

@zz85
Contributor
zz85 commented Mar 17, 2012

yeah, maybe not the most perfect, but i think problem is resolved! :)

another decorated knot just for funs :)

(the interesting ribbon like extrusion was done setting radius segment to 2)
@WestLangley
Collaborator

Nice work, @zz85 !

I'm not sure, however, it is a good idea to have a discontinuity in the binormal where the two ends stitch together. TubeGeometry has a hack to prevent that from happening, but it doesn't work in the general case.

EDIT: It looks like this problem has been solved. http://www.cs.indiana.edu/pub/techreports/TR407.pdf. I see that the author mentions that one thing you could do is measure the total binormal rotation, and then backtrack, and distribute that rotation equally around the curve. Well, that seems rather involved...

@zz85
Contributor
zz85 commented Mar 17, 2012

wow, that paper looks like greek to me.

the link I had above about rotation minimizing frames via double reflection could be a simpler way, although its still too much to go into my head now... http://research.microsoft.com/en-us/um/people/yangliu/publication/computation%20of%20rotation%20minimizing%20frames.pdf

hopefully the current implementation is good enough for most use cases now. (without the wireframes, how much difference would be noticeable ?)

@alteredq
Contributor

hopefully the current implementation is good enough for most use cases now. (without the wireframes, how much difference would be noticeable ?)

I think the concern may be about texturing / normal mapping: I guess "proper" solution would have chance to be seamless while the current "twisted" one may have discontinuities?

Speaking about texturing - I was trying to understand what causes weirdness in extruded textured objects I mentioned upthread (visible seams and changes of shade dependent on angle of view) and it seems this came from mipmapping:

alteredq@1ebe7df

@WestLangley
Collaborator

without the wireframes, how much difference would be noticeable ?

TorusKnotGeometry stitches the ends together. If we did so here, there would be trouble.

http://imgur.com/54JoY

@zz85
Contributor
zz85 commented Mar 17, 2012

ahhh... didn't seem very obvious with more radius segments and basic material (and open splines), but i'm getting the idea...

still trying to absorb that RMF thing, but unfortunately i don't think its going into my head right now...

We used a double reflection method [1] to compute 
the RMF. The double reflection method can be thought 
of as projecting the spline onto a sphere, and 
maintaining the RMF of the spline by using the normal 
of the sphere, tangent of the spline function by using 
the next sample, and the bitangent as a cross product 
of the previous two vectors. We also checked if our 
normal vector would flip abruptly, and subsequently 
negate the normal vector. We find that the double 
reflection method generates very smooth sweeps from 
our given polylines.

http://www.cs.berkeley.edu/~sequin/CS285/2011_REPORTS/CS285%20final%20paper_Andrew&Brandon.pdf

@zz85
Contributor
zz85 commented Mar 17, 2012

seems like blender also suffers from extrusion problems (bottom of the page) http://wiki.blender.org/index.php/Doc:2.4/Tutorials/Modeling/Curves/Extrude_Along_Path

@WestLangley
Collaborator

Ok, the approach that makes the most sense to me is to use parallel transport frames. It is described here:

http://www.cs.indiana.edu/pub/techreports/TR425.pdf. This is doable.

The approach is to:
(1) compute the tangent vectors for each point on the path (ahead of time),
(2) compute the slowly-varying normal and binormal vectors for each point on the path, and
(3) if the curve is closed, postprocess the vectors so the first and last normal vectors are the same.

Once the coordinate frames are computed, the mesh can be extruded.

@WestLangley
Collaborator

@zz85

TubeGeometry now supports closed paths. It guarantees that the the Frenet frames are continuous when the ends are stitched together. Hopefully this will lead to proper texturing. Have a look.

https://github.com/WestLangley/three.js/blob/dev-tubeGeo/src/extras/geometries/TubeGeometry.js

Here is a fiddle: http://jsfiddle.net/rCxkY/4/

@zz85
Contributor
zz85 commented Mar 23, 2012

nice work @WestLangley ! i see some geometry gymnastics going on :)

i've started to merge your changes and would be updating the examples and check if its working well..

@zz85
Contributor
zz85 commented Mar 25, 2012

@WestLangley i update my example a little to play around with the extrusions.

zz85@70ee0cf...72f462e

somehow the closed end doesn't stitch in certain cases, but i'm not too sure...

@WestLangley
Collaborator

@zz85 you have 2 forms of the variables closed and debug -- with and without v at the end.

@zz85
Contributor
zz85 commented Mar 25, 2012

@WestLangley i've fixed the checkbox issue. some shapes work well, but some shapes doesn't...

@WestLangley
Collaborator

@zz85 Your closed variable is FALSE in every call to the TubeGeometry constructor.

@zz85
Contributor
zz85 commented Mar 26, 2012

nice catch @WestLangley ! turns out that the browser seems to be overwriting the closed variable. problem fixed after changing it to closed2

@zz85
Contributor
zz85 commented Apr 1, 2012

now that I'm using TubeGeometry internally in ExtrudeGeometry, does it make sense to refactor the TNB calculations so that they can be shared in both classes, and potentially for camera on spline which requires stabilization?

Perhaps...

var frames = new THREE.SplineFrames(spline, segments, closed);
var tangents = frames.tangents[];
var normals = frames.normals[];
var binormals = frames.binormals[];

Somehow I'm still a little torn about how the initial normals should be computed for spline extrusion - the orientation effects are perhaps more obvious for a shape extrusion compared to a tube extrusion. Perhaps we could allow the user to define their initial normal plane? Then again maybe more use cases might help, creating too large a shape extrusion geometry might also not be practical due to the large amount of vertices and faces involved.

@WestLangley
Collaborator

@zz85 The parallel transport frames logic in TubeGeometry is very specific to that application. In the case of a camera spline requiring stabilization, that is a similar problem, but will require different logic due to both the initial normal selection and (presumably) the desire to keep the camera level. I wouldn't refactor at this point. Wait until you see how ExtrudeGeometry works out.

And, regarding ExtrudeGeometry, do you have a link to a live example -- or is it in your fork somewhere, and I just can't find it? I'd like to understand where you are heading with this -- and what the issues are...

@zz85
Contributor
zz85 commented Apr 2, 2012

@WestLangley Its in my branch extrude_spline_rebasing https://github.com/zz85/three.js/tree/extrude_spline_rebasing, now I'll also push it to my master.

the link for the the example and ExtrudeGeometry is at here

the parallel transport frames is quite specific, but now they would be used in TubeGeometry, ExtrudeGeometry and used for the camera animation in webgl_geometry_extrude_splines.html

If we do not put it into a new class, we could use still refactor it as a util function like
THREE.TubeGeometry.parrellelTransportFrames(spline, segments, closed); or THREE.GeometryUtils.parrallel(spline, segments, closed);

btw, do you have a homepage or twitter? ;)

@zz85
Contributor
zz85 commented Apr 3, 2012

@WestLangley

I've now done the refactoring to contain TNB calculations in THREE.TubeGeometry.FrenetFrames and have special care that that TubeGeometry and ExtrudeGeometry are not broken. I think this is better because there's less duplication of code, and more also efficient than ExtrudeGeometry to use TubeGeometry internally. Also, if there's another algorithm to calculate the TNBs, one just have to swap out the FrenetFrames() function.

zz85@ecb2059...bbfb804

@WestLangley
Collaborator

@zz85 OK. Sorry, I am not able to help with this right now, but I will make sure to have a look.

EDIT: Your changes to TubeGeometry do not look right to me. In particular, line 126 cannnot be commented out.

        // vec.cross( tangents[ 0 ], normal ).normalize();

643a338

@zz85
Contributor
zz85 commented Apr 3, 2012

thanks. strangely enough, i'm not sure how the code got there, but things felt like it was still running. fixed that section of the code now.

zz85@1e1a02d

@WestLangley
Collaborator

@zz85

i'm not sure how the code got there

Uh, dude, this doesn't sound good to me. :/

What was your rationale for re-entering alternative methods of computing the initial Frenet frame in TubeGeometry? Was the algorithm not working properly?

643a338

@zz85
Contributor
zz85 commented Apr 3, 2012

TubeGeometry should work working really well now. I think I was testing the effects of the initial frame with ExtrudeGeometry's extrude path. For example if you are extruding a smiley face shape along a spline, you might want to orientating the eyes to be facing up. The same algorithm might work well too, I should have tested it a little more...

https://github.com/zz85/three.js/blob/bbfb8044f55e2d6dd0b047eb7286c27204dadd6c/examples/webgl_geometry_extrude_shapes.html#L181

@zz85
Contributor
zz85 commented Apr 10, 2012

@WestLangley what do non-planar means? would it be better to tessellate the tube into triangles like http://prideout.net/blog/?p=44 ?

@WestLangley
Collaborator

@zz85

what do non-planar means?

The four vertices of each extruded quad face are not in the same plane.

would it be better to tessellate the tube into triangles

I think it would. However, I asked this question in #1664, and I don't think there was a conclusion yet. Maybe you can stir the pot a little. ;-)

@zz85
Contributor
zz85 commented Apr 11, 2012

okay, i could give it a shot implementing tubegeometry with parametricsurface :)

@zz85
Contributor
zz85 commented Apr 11, 2012

tada!! Triangulated TubeGeometry using ParametricGeometry internally...

http://jsbin.com/opebux/3/edit#javascript,live

@mrdoob
Owner
mrdoob commented Apr 12, 2012

Looks good! :D

@zz85
Contributor
zz85 commented Apr 18, 2012

@WestLangley interesting article about perpendicular vectors :) http://blog.selfshadow.com/2011/10/17/perp-vectors/

@ashawthing

I started this thread at least 4 months ago and I can't believe the outcome of my original message. Brilliant work, I really appreciate it and I'm sure plenty of other people will or do already.

I'm using the tube to highlight a walk route in a walk planner and it almost does what I want it to do. The problem is when the route takes a 90 degree turn (e.g. to cross the road), the SplineCurve3 generates a large arc instead of a sharp turn.

Before I create my own path object which ensures that every interpolated point returned is on the direct path between points can anybody suggest a way of doing what I want without creating a new path type of path?

BTW - I tried duplicating each of my points in the source to SplineCurve3 and this gives me a better looking route with sharper turns but it contains a little loop (knot) at each turn.

@zz85
Contributor
zz85 commented May 2, 2012

@ashawthing since SplineCurve uses the catmull-rom curve, the bends are not supposed to be sharp. You could try using LineCurve with CurvePath. I not sure about using Path since its more for 2d for now.

@amoffat
amoffat commented Aug 20, 2012

I know this is a really old issue, but I found a great resource for using quaternions to minimize torsion while retaining periodicity ftp://ftp.cs.indiana.edu/pub/hanson/Siggraph01QuatCourse/quatvis3.pdf

@mrdoob mrdoob closed this Sep 29, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment