Search code examples
math3dvrml

How to create a cylinder between origin and some coordinates in VRML


I'm creating some files in VRML 2.0 programmatically. I need to construct a cylinder which has its bottom at the origin and its top at a given coordinate, but I'm having some problem figuring out the rotation. I have googled it, but the documentation on VRML 2.0 appears to be very scarce.

I assumed that spherical coordinates would work best for what I'm trying to do, so I computed the spherical coordinates (r, theta, phi) for the target point (x,y,z). I then created the file below.

#VRML V2.0 utf8

DEF v1 Transform {
    translation 0 0 0
    children Shape {
        geometry Sphere {radius .5}
    }
}
DEF v2 Transform {
    translation x y z
    children Shape {
        geometry Sphere {radius .5}
    }
}
DEF edge Transform {
    translation 0 0 0
    children Transform {
        rotation 0 1 0 theta-pi/2
        children Transform {
            rotation 0 0 1 phi-pi/2
            children Transform {
                translation 0 r/2 0
                children Shape {
                    geometry Cylinder {
                        radius .08
                        height r
                    }
                }
            }
        }
    }
}

And here is a version with some example values:

#VRML V2.0 utf8

DEF v1 Transform {
    translation 0 0 0
    children Shape {
        geometry Sphere {radius .5}
    }
}
DEF v2 Transform {
    translation 4 3 3
    children Shape {
        geometry Sphere {radius .5}
    }
}
DEF edge Transform {
    translation 0 0 0
    children Transform {
        rotation 0 1 0 -0.54041949679
        children Transform {
            rotation 0 0 1 -0.92729521779
            children Transform {
                translation 0 2.915475947 0
                children Shape {
                    geometry Cylinder {
                        radius .08
                        height 5.830951895
                    }
                }
            }
        }
    }
}

If you view this last file, you will see that the cylinder is actually quite close, but not quite there yet.


Solution

  • O.K., a long time since I did this stuff, but I think I've got why your approach doesn't work and how to do it. Calculating using spherical coordinates, as you tried, is from a FIXED reference frame that doesn't itself rotate. But once you rotate around y in your code in VRML, the z axis is no longer pointed where it had been, but rotated as well. Your reference frame changed.

    Now one approach is to use Euler angles and multiple x, y, and z rotations , but you should be able to do a single rotation once you figure out the quaternion (which represents the x, y, and z coordinates of a rotation vector and the amount of rotation). See this Q&A for where the formula comes from.

    Approach: You want the re-oriented y axis in the cylinder's coordinate system to align with a vector from the origin to the given coordinate, so you want a rotation to move point 0,r,0 to the new specified x, y, z. Here's how to do it:

    1. v1 is 0,r,0 (r is the height of the cylinder)
    2. v2 is the coordinates where you want the center of the top to be
    3. vector a = crossproduct(v1,v2)
    4. Normalize vector a. The VRML spec. says it expects a normalized rotation vector, so better to be safe than sorry. To normalize, compute the length of vector a and then divide the x, y, and z components by the length.
    5. Rotation angle is length(v1) * length(v2) + dotproduct(v1,v2)
    6. So you just need a single rotation transform, where you use the x, y, and z values for the normalized vector a calculated in step 4 and the angle calculated in step 5.