Toby Smith

Cylinder between two points (OpenGL C++)

4th December 2010

Whilst working on one of my projects this year for uni I was looking for some code to draw a cylinder between two points (using OpenGL). There were a couple of solutions out there, but they weren’t that great.

I couldn’t find one that worked reliably and simply (without lots of different if statements trying to catch different cases). Anyway, after a bit of thought I knocked this one out. It’s actually a lot simpler than you think…which is probably why people haven’t bothered to post it.

Anyway…enjoy some pseudo code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Vector3D a, b; (the two points you want to draw between)
 
// This is the default direction for the cylinders to face in OpenGL
Vector3D z = Vector3D(0,0,1);         
// Get diff between two points you want cylinder along
Vector3D p = (a - b);                               
// Get CROSS product (the axis of rotation)
Vector3D t = CROSS_PRODUCT (z , p); 
 
// Get angle. LENGTH is magnitude of the vector
double angle = 180 / PI * acos ((DOT_PRODUCT(z, p) / p.LENGTH());
 
glTranslated(b.x,b.y,b.z);
glRotated(angle,t.x,t.y,t.z);
 
gluQuadricOrientation(YourQuadric,GLU_OUTSIDE);
gluCylinder(YourQuadric, RADIUS, RADIUS, p.LENGTH(), SEGS1, SEGS2);

Hope that helps someone out there.

Comments

#1 Tim L 9:59 pm 15th February 2011

I stumbled on your post today… And found it very useful.

I use a scene graph library called OpenSceneGraph

Based on your post… here is how to draw a cylinder between two points in Open Scene Graph

///////////////////////////////////////////////////////////////////////////////
// void AddCylinderBetweenPoints(osg::Vec3 StartPoint, osg::Vec3 EndPoint, float radius, osg::Vec4 CylinderColor, osg::Group *pAddToThisGroup)
/*
The following function creates a cylinder between two points with a given radius and color.
*/
void AddCylinderBetweenPoints(osg::Vec3 StartPoint, osg::Vec3 EndPoint, float radius, osg::Vec4 CylinderColor, osg::Group *pAddToThisGroup)
{
osg::ref_ptr geode = new osg::Geode;
osg::Vec3 center;
float height;
osg::ref_ptr cylinder;
osg::ref_ptr cylinderDrawable;
osg::ref_ptr pMaterial;

height = (StartPoint- EndPoint).length();
center = osg::Vec3( (StartPoint.x() + EndPoint.x()) / 2, (StartPoint.y() + EndPoint.y()) / 2, (StartPoint.z() + EndPoint.z()) / 2);

// This is the default direction for the cylinders to face in OpenGL
osg::Vec3 z = osg::Vec3(0,0,1);

// Get diff between two points you want cylinder along
osg::Vec3 p = (StartPoint – EndPoint);

// Get CROSS product (the axis of rotation)
osg::Vec3 t = z ^ p;

// Get angle. length is magnitude of the vector
double angle = acos( (z * p) / p.length());

// Create a cylinder between the two points with the given radius
cylinder = new osg::Cylinder(center,radius,height);
cylinder->setRotation(osg::Quat(angle, osg::Vec3(t.x(), t.y(), t.z())));

cylinderDrawable = new osg::ShapeDrawable(cylinder );
geode->addDrawable(cylinderDrawable);

// Set the color of the cylinder that extends between the two points.
pMaterial = new osg::Material;
pMaterial->setDiffuse( osg::Material::FRONT, CylinderColor);
geode->getOrCreateStateSet()->setAttribute( pMaterial, osg::StateAttribute::OVERRIDE );

// Add the cylinder between the two points to an existing group
pAddToThisGroup->addChild(geode);
}

#2 KamaKase 12:45 am 24th March 2011

Awesome, I’m glad it helped. Thanks for sharing more code too.

#3 Bear 12:10 pm 6th April 2011

it works
But could you explain why it works?

#4 Given 兩點,畫個 cylinder 連住 | 學習筆記 12:16 pm 7th April 2011

[…] 轉自:http://www.thjsmith.com/40/cylinder-between-two-points-opengl-c […]

#5 KamaKase 10:30 am 9th April 2011

Sure.

We calculate p as the vector going from b to a (p = a – b).
z is simply the OpenGL default cylinder draw direction. If we did no rotation, it would be drawn in that orientation.
The cross product of z and p gives a vector perpendicular to both p and z, (this is t). This is then the vector the rotation pivots about.
We then use the dot product to obtain the angle needed to rotate (the division by the length is purely because I haven’t normalised p).
Then, we just perform the rotation.

Does that help?

#6 Bear 1:37 am 17th April 2011

Thx, it helps

#7 JC 5:26 pm 18th February 2012

Thanks!

Leave a Comment

http://www.thjsmith.com/feed">RSS Feed
  • Terms of use
  • Privacy Policy