1

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.

  • Doesn't the cylinder node by default CENTER on the origin? If you want the base to be at the origin, you need to translate it by 1/2 the height. Also, is the height of the cylinder computed based on where you want the top to be, and is the point for the top the middle of the top? There are some good references at http://graphcomp.com/info/specs/sgi/vrml/spec/ and http://accad.osu.edu/~pgerstma/class/vnv/resources/info/AnnotatedVrmlRef/Book.html – ViennaMike Apr 22 '15 at 16:19
  • The cylinder is indeed centered on the origin, but I already translated, so that's not the problem. The translation is the seventh line of the edge DEF. The point for the top is indeed the middle. I knew the first reference, but it is very vague about the specifics of the rotation. The second reference is new to me, and I will have a look at it. – user3031033 Apr 23 '15 at 06:27

1 Answers1

2

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.
ViennaMike
  • 2,207
  • 1
  • 24
  • 38