AB4D Forum

Full Version: Rotated cylinders
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I would like to be able to create rotated cylinders. For example, draw a cylinder with the following specifications:

Top of Cylinder center coordinate = (3,7,5)
Bottom of Cylinder center coordinates = (1, -3, 2)
Diameter = 4

Is that possible with your cylinder object? Or could you explain how to do a 3d rotation of your standard cylinder object that would work for this situation?

I will only know the coordinates at runtime, so the code would need to be in C# (not xaml). There will be hundreds of cylinders in a drawing.

Thanks in advance!
Cylinder object in the current version of Ab3d.PowerToys is always pointing up.

But you can use TubeVisual3D that allows you to specify the "height direction".
Usually TubeVisual3D also renders the inner tube. But you can set the InnerRadius to 0 and this will remove the inner tube and produce a cylinder.

For example:
Code:
var startPosition = new Point3D(1, -3, 2);
var endPosition = new Point3D(3, 7, 5);

Vector3D tubeDirection = endPosition - startPosition;

var tubeVisual3D = new TubeVisual3D()
{
    BottomCenterPosition = startPosition,
    HeightDirection = tubeDirection,
    Height = tubeDirection.Length,
    InnerRadius = 0,
    OuterRadius = 4,
    Material = new DiffuseMaterial(Brushes.Green)
};

MainViewport.Children.Add(tubeVisual3D);


If you need to get MeshGeometry or GeometryModel3D (instead of Visual3D), you can use Ab3d.Meshes.TubeMesh3D.

When checking the code for Tube I have seen that even when the InnerRadius is set to 0, the positions and triangles for the inner tube are still generated. In most cases this should not be a problem. But anyway, I will improve the code so that in case when InnerRadius is set to 0 a simple cylinder will be generated without the inner tube.


EDIT:
Another option that creates more optimal cylinder (without inner tube positions and triangles) is to use LatheMesh3D. LatheMesh3D is used to create lathe objects that are created with rotating the specified segments around an axis - each segment specifies a radius and an offset. A typical lathe mesh is a vase - different offsets from bottom have different radius.

A cylinder is a very simple lathe object with only two segments and where both segments have the same radius.

The following code can be used to create cylinder with LatheMesh3D:

Code:
var startPosition = new Point3D(1, -3, 2);
var endPosition = new Point3D(3, 7, 5);
double radius = 4;

var sections = new Ab3d.Meshes.LatheSection[2];

sections[0] = new Ab3d.Meshes.LatheSection(0, radius, true);
sections[1] = new Ab3d.Meshes.LatheSection(1, radius, true);

var latheMesh3D = new Ab3d.Meshes.LatheMesh3D(startPosition, endPosition, sections,
                                                segments: 30, // this can be adjusted to create lower or higher detailed cylinder
                                                isStartPositionClosed: true,
                                                isEndPositionClosed: true,
                                                generateTextureCoordinates: true);

var cylinderGeometry = latheMesh3D.Geometry;

var material = new DiffuseMaterial(Brushes.Green);
var model3D = new GeometryModel3D(cylinderGeometry, material);

var visual3D = new ModelVisual3D()
{
    Content = model3D
};

MainViewport.Children.Add(visual3D);
Works perfectly! Thank you so much for your extremely prompt reply!
Great! I am glad that this works for you.

If you would like to slightly reduce the number of positions and triangles that are created with TubeVisual3D, you can also use LatheMesh3D - see my updated answer.
Thank you! Both methods work great.
By the way, the second method resulted in a noticeable performance improvement for a drawing with lots of cylinders. Thanks again for the update.
If you do not need to change the cylinders after they are created, you can get an additional performance improvement if you group all the cylinderGeometry objects into one Model3DGroup and Freeze the Model3DGroup at the end.

This performance tip is very noticeable when using Ab3d.DXEngine (DirectX 11 rendering engine) - in this case you could probably render hundred thousands cylinders.