# Raytracing Oriented Cylinders

This topic is 4725 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I have seen equations for points on the surface of a cylinder. However, those were for axis aligned cylinders. I would like to know if there is a simple equation for the points on the surface of an oriented cylinder that would have a direction vector.

##### Share on other sites
just transform your ray by the cylinders inverse transform and do the axis aligned method

##### Share on other sites
Quote:
 Original post by Anonymous Posterjust transform your ray by the cylinders inverse transform and do the axis aligned method

Now there has to be a more efficient and more logical method... Involving the axis vector of the cylinder.

##### Share on other sites
That's the more wefficient and logical way

##### Share on other sites
Well, how do you do that without using transform matrices? I'm looking for a simple say, and it seems to me like there would be a way to obtain a vector equation for the oriented cylinder.

##### Share on other sites
Well it sound like you know how to solve it then.
But in my experience of all the ways you can find
transforming the line to the local space of the cylinder is the simplest and more efficient, because it eliminates some of the degree of fredom on the problem. That is what matrices are for, they simplify calculations they do not make then more difficult.
Ant way if you find a better way let my know.

##### Share on other sites
Well, I've been thinking about it, and I think I'm on the right track. We simply have to use the properties of a cylinder. I will start with infinite cylinders. Limiting the length should then be rather trivial.

We define an oriented cylinder by 3 parameters:
- An origin point (3D vector)
- A direction (3D vector)

As you can see, the cylinder has an origin and a direction. Its basically just a line (or ray, but we don't limit it to only one direction), with a radius around it, that is, all points on its surface are equidistant from the axis ray.

For a ray, we know that the distance between the ray origin and the closest point to a random point in space is equal to:

1) OrigDistance = DotProduct(RayDirection , SpacePoint - RayOrigin)

We can actually get the closest point on the cylinder axis by applying this principle:

2) AxisPoint = CylOrigin + DotProduct(SpacePoint - CylOrigin) x CylDirection

Then, we know that the distance between a point on the surface is equal to the radius of the cylinder... So we substitute spacepoint by the point which should be the intersection of the ray and the cylinder:

3) Distance(RayPoint, CylOrig + Dot(RayPoint - CylOrig) x CylDir) = R

Now, its a matter of substituting the ray intersection point by its definition:

4) RayPoint = RayOrig + t x RayDir

Then we isolate t, and since this involves a square root, there should be two possible values for it, which is coherent with the fact that a ray should intersect a cylinder in two points, unless it intersects exactly on the surface.

This should work right. If anyone wants to bother isolating t, I'm going to sleep for the moment, and this might be helpful to others ;) Otherwise I'm going to have to re-check my linear algebra books tommorow.

##### Share on other sites
ive tried both methods, and there wasnt a significant difference in speed between either in my implementation.

however, i stuck with the intersection in cylinder space thing, because it allowes all sorts of funky squashed cylinders aswell.

however, calculating normals in worldspace has a catch: you should first multiply the normal with the cylinders adjunct matrix, then normalize it.
example: PositiontoNormal = WorldtoLocal.Transpose() * XYPlane * WorldtoLocal;
this will transform any point in worldspace on the surface of a z-aligned cylinder to an unnormalized normal in worldspace.

also, you can just normalize by dividing by a radius, but youll have to do a full normalize, which you might not find too appealing.

here is my code for an arbitrarily aligned cylinder:

	void Trace(Ray ray){		//relative distance		Vector3 r;		r.x = Void.World.Position.x - ray.pos.x;		r.y = Void.World.Position.y - ray.pos.y;		r.z = Void.World.Position.z - ray.pos.z;				Vector3 t1;		t1.x = ray.dir.y*axis.z - ray.dir.z*axis.y;		t1.y = ray.dir.z*axis.x - ray.dir.x*axis.z;		t1.z = ray.dir.x*axis.y - ray.dir.y*axis.x;		Vector3 t2;		t2.x = r.y*axis.z - r.z*axis.y;		t2.y = r.z*axis.x - r.x*axis.z;		t2.z = r.x*axis.y - r.y*axis.x;				float A, B, C, D;		A =  t1.x*t1.x + t1.y*t1.y + t1.z*t1.z;		B = (t1.x*t2.x + t1.y*t2.y + t1.z*t2.z) * 2;		C =  t2.x*t2.x + t2.y*t2.y + t2.z*t2.z - Radius*Radius;		D = B*B - 4*A*C;				if (D >= 0){			D = sqrt(D);					float min, max;			max = (B + D) / (2 * A);			if (max > 0){							//in front of ray				min = (B - D) / (2 * A);				if (min > 0){						//ouside					if (max > 1){					//doesnt exit						if (min > 1){				//doesnt enter							iv.Reset(false);						}else{						//ends inside							iv.Set(on, min, false);						}					}else{							//goes trough						iv.Set(on, min, off, max, false);					}				}else{								//inside					if (max > 1){					//doesnt exit						iv.Reset(true);					}else{							//exits						iv.Set(off, max, true);					}				}				return;			}		}		//reset interval		iv.Reset();	}

##### Share on other sites
equation of infinite cylinder

((P - C) x H)^2 = r^2

it's like a sphere where

(P - C)^2 = r^2

and H being the direction of the cylinder

second order equation, ect...

if H not normalised

((P - C) x H)^2 = r^2 * (H.Dot(H))

also, to deal with caps, it's just like when doing box-ray tests. YOu have to work with slabs.

##### Share on other sites
Thank you Mr Oliii. I knew it had to be possible to simplify it. Now its just a matter of substituting the ray equation and isolating t. Just one detail though.

((P - C) x H)^2 = r^2

By this, do you mean cross product with H? And if so, that would be magnitude of the cross product of (P - C) with H, squared?

• 22
• 10
• 19
• 15
• 14