To create a 3D mesh from a 2D shape use Triangulator class and MeshFactory.CreateExtrudedMesh method. The Triangulator defines the triangles that fill the 2D shape. The CreateExtrudedMesh method creates a 3D mesh by extruding the 2D shape in the specified 3D direction.

See the "Advanced 3D models / Extruded mesh" sample for details on how to use that for simple shapes and for shapes with holes (use the latest sample that comes with v2.0 RC).

Note that the order of positions in the 2D shape is important - the positions should be oriented in a clockwise direction. Also the shape should be defined in such a way that its center is at (0, 0).

So, the most simple way is to first define the positions for the 2D shapes for the cross-sections. Then triangulate them. Then for each beam and column create a mesh by using the CreateExtrudedMesh that gets the direction of the beam or column (the length is defined by the length of the extrudeVector) and modelOffset (defines the start position of the beam or column).

But if you want to show many (hundreds) of beams and columns, then it is more efficient to create "standard normalized meshes" for each cross-section. In this case the shape should be created with the center (0,0) and size (1, 1) - so shape's bound should be from -0.5 to +0.5. Then extrude that shape to the (1,0,0) direction (length is 1). This will give you a 1x1x1 mesh that can then be positioned and scaled to any target position and size by using the matrix transformation.

I am just finishing the release of SharpEngine v2.0 and do not have to create such sample now, but I will try to add that sample after the official release. Until then, you can use the following methods to get the transformation matrix:

Code:

` public static Matrix4x4 GetMatrixFromPositionsAndSize(Vector3 startPosition, Vector3 endPosition, Size size)`

{

// We need to offset the Mesh by 0.5 on xAxis so that the (0,0,0) will be on the left edge of the mesh (without this (0,0,0) is in the center of the mesh).

// This way the mesh will be positioned so that it will start at startPosition.

// If this step is skipped, then startPosition will position center of the mesh.

//

// This step can be skipped if mesh is created in such a way that it is already positioned so that its left edge starts at (0, 0, 0).

//

// See also comments in GenerateSampleObjects method.

var direction = endPosition - startPosition;

var length = direction.Length(); // length will be used for x scale

var scale = new Vector3(length, (float)size.Height, (float)size.Width);

//direction.Normalize(); // Because we already have length, we can quickly normalize by simply dividing by length

direction /= length;

var matrix = Matrix4x4.CreateScale(scale) *

GetMatrixFromNormalizedDirection(direction);

matrix.M41 = startPosition.X;

matrix.M42 = startPosition.Y;

matrix.M43 = startPosition.Z;

return matrix;

}

// directionVector must be normalized

public static Matrix4x4 GetMatrixFromNormalizedDirection(Vector3 normalizedDirectionVector)

{

// The first three rows in the upper left 3x3 part of the matrix represents the axes of the coordinate system defined by the matrix.

// For example in the identity matrix the xAxis is 1,0,0; yAxis is 0,1,0; zAxis is 0,0,1

// With this knowledge we can create a matrix that will orient the transformed positions based on the specified direction vector.

// The direction vector represents the xAxis in the new coordinate system.

// To get the full matrix, we need to calculate the other two axes.

//var xAxis = normalizedDirectionVector;

var yAxis = CalculateUpDirectionFromNormalizedDirection(normalizedDirectionVector);

// Once we have the direction and up axis, we can get the zAxis with calculating the perpendicular axis to those two

var zAxis = Vector3.Cross(normalizedDirectionVector, yAxis);

var rotationMatrix = new Matrix4x4(normalizedDirectionVector.X, normalizedDirectionVector.Y, normalizedDirectionVector.Z, 0,

yAxis.X, yAxis.Y, yAxis.Z, 0,

zAxis.X, zAxis.Y, zAxis.Z, 0,

0, 0, 0, 1);

return rotationMatrix;

}

// TODO: Add support for other coordinate systems and not just to Y up (0,1,0)

public static Vector3 CalculateUpDirectionFromNormalizedDirection(Vector3 normalizedLookDirection)

{

// To get the up direction we need to find a vector that lies on the xz plane (horizontal plane) and is perpendicular to Up vector and lookDirection.

// Then we just create a perpendicular vector to lookDirection and the found vector on xz plane.

var horizontalVector = Vector3.Cross(new Vector3(0, 1, 0), normalizedLookDirection);

// First we need to check for edge case - the look direction is in the same direction as UpVector - the length of horizontalVector is 0 (or almost zero)

var length = horizontalVector.Length();

if (length < 0.001)

horizontalVector = Vector3.UnitZ; // Any vector on xz plane could be used

else

horizontalVector /= length; // Normalize

var upDirection = Vector3.Cross(normalizedLookDirection, horizontalVector);

return upDirection;

}

// TODO: Add support for other coordinate systems and not just to Y up (0,1,0)

public static Vector3 CalculateUpDirection(Vector3 lookDirection)

{

// To get the up direction we need to find a vector that lies on the xz plane (horizontal plane) and is perpendicular to Up vector and lookDirection.

// Then we just create a perpendicular vector to lookDirection and the found vector on xz plane.

var horizontalVector = Vector3.Cross(new Vector3(0, 1, 0), lookDirection);

// First we need to check for edge case - the look direction is in the UpVector direction - the length of horizontalVector is 0 (or almost zero)

if (horizontalVector.LengthSquared() < 0.0001) // we can use LengthSquared to avoid costly sqrt

return Vector3.UnitZ; // Any vector on xz plane could be used

var upDirection = Vector3.Cross(lookDirection, horizontalVector);

upDirection = Vector3.Normalize(upDirection);

return upDirection;

}