2

I'm struggling to write a script in 3ds Max to create a tube with weight changing along it.

As input I have points, which this tube should pass, also orientation and width at those points. This tube is supposed to be a visualization of something, and for me is important to have it as one object in order to map a texture on it later (like, color will be another visualized parameter).

I'm relatively new to the maxscript, so I might miss an obvious approach, but so far I found only extrusion applicable for the task.

Since I need tapering at each step I thought first to make a bunch of initial circles and then extrude them into tubes. But in order to arrive to next point, I need to rotate the circle according to direction of the tube. After some searching I found a way to rotate a single face, but it seems I'm messing up with the vector to angle transformation, because tubes do not look like they are supposed to.

Could you please tell me where I'm mistaken and, even more important, if there is a better way to draw tubes with variable width?

Here is the code:

--first, matrix with all the points of 5 tubes. for each point the first three numbers are position, next 3 - direction, then width, but I don't use width in this code, since I encountered problems even befor approaching tapering.
tubeMatr = #(#(#(-0.252, -0.282, 0.02, 0.025, 0.953, 0.302, 181.2), #(-0.252, -0.282, 0.074, 0.045, 0.957, -0.183, 42.16), #(-0.252, -0.282, 0.128, 0.045, 0.927, -0.341, 25.83), #(-0.252, -0.282, 0.182, 0.013, 0.903, -0.407, 23.73), #(-0.252, -0.191, 0.02, 0.062, 0.955, 0.282, 317.7)), #(#(-0.252, -0.272, 0.023, 0.03, 0.952, 0.274, 192.8), #(-0.251, -0.272, 0.072, 0.06, 0.945, -0.195, 51.41), #(-0.251, -0.273, 0.124, 0.056, 0.916, -0.361, 27.39), #(-0.252, -0.273, 0.178, 0.026, 0.892, -0.427, 24.9), #(-0.251, -0.181, 0.023, 0.069, 0.955, 0.25, 309.6)), #(#(-0.251, -0.263, 0.026, 0.036, 0.95, 0.245, 203.5), #(-0.251, -0.263, 0.07, 0.073, 0.934, -0.204, 62.15), #(-0.251, -0.263, 0.121, 0.068, 0.906, -0.381, 29.05), #(-0.251, -0.264, 0.173, 0.039, 0.88, -0.447, 26.13), #(-0.25, -0.172, 0.025, 0.074, 0.958, 0.226, 304.1)), #(#(-0.251, -0.253, 0.028, 0.044, 0.947, 0.216, 213.4), #(-0.25, -0.253, 0.068, 0.084, 0.924, -0.21, 74.34), #(-0.25, -0.254, 0.117, 0.08, 0.895, -0.401, 30.81), #(-0.251, -0.255, 0.169, 0.051, 0.87, -0.467, 27.44), #(-0.25, -0.162, 0.028, 0.077, 0.961, 0.21, 300.6)), #(#(-0.25, -0.244, 0.03, 0.051, 0.943, 0.188, 223.0), #(-0.249, -0.244, 0.066, 0.094, 0.915, -0.214, 87.96), #(-0.249, -0.245, 0.113, 0.092, 0.885, -0.423, 32.69), #(-0.25, -0.246, 0.164, 0.063, 0.859, -0.486, 28.84), #(-0.249, -0.153, 0.03, 0.079, 0.965, 0.199, 298.8)), #(#(-0.25, -0.234, 0.032, 0.06, 0.939, 0.16, 232.4), #(-0.248, -0.235, 0.064, 0.103, 0.907, -0.215, 102.9), #(-0.248, -0.236, 0.109, 0.106, 0.875, -0.445, 34.7), #(-0.25, -0.238, 0.159, 0.075, 0.849, -0.505, 30.33), #(-0.248, -0.143, 0.032, 0.08, 0.971, 0.193, 298.3)), #(#(-0.249, -0.225, 0.034, 0.068, 0.934, 0.133, 241.8), #(-0.247, -0.226, 0.062, 0.11, 0.9, -0.214, 119.2), #(-0.247, -0.228, 0.104, 0.12, 0.865, -0.468, 36.87), #(-0.249, -0.229, 0.154, 0.087, 0.84, -0.525, 31.93), #(-0.247, -0.133, 0.034, 0.079, 0.973, 0.19, 301.0)), #(#(-0.249, -0.216, 0.035, 0.073, 0.933, 0.115, 246.9), #(-0.246, -0.217, 0.06, 0.111, 0.9, -0.192, 138.0), #(-0.246, -0.219, 0.1, 0.132, 0.857, -0.486, 40.28), #(-0.248, -0.221, 0.149, 0.098, 0.83, -0.544, 33.64), #(-0.247, -0.124, 0.035, 0.077, 0.973, 0.19, 305.7)), #(#(-0.248, -0.206, 0.036, 0.075, 0.937, 0.11, 247.8), #(-0.245, -0.208, 0.058, 0.101, 0.912, -0.136, 158.1), #(-0.245, -0.211, 0.095, 0.126, 0.866, -0.443, 54.04), #(-0.247, -0.213, 0.144, 0.101, 0.819, -0.558, 35.67), #(-0.246, -0.114, 0.037, 0.075, 0.974, 0.19, 311.5)), #(#(-0.247, -0.197, 0.037, 0.076, 0.941, 0.108, 249.5), #(-0.244, -0.199, 0.056, 0.094, 0.923, -0.09, 175.0), #(-0.244, -0.202, 0.09, 0.119, 0.878, -0.389, 70.1), #(-0.246, -0.204, 0.138, 0.102, 0.809, -0.566, 38.7), #(-0.245, -0.104, 0.039, 0.073, 0.974, 0.191, 318.5)), #(#(-0.246, -0.188, 0.039, 0.076, 0.947, 0.108, 251.9), #(-0.243, -0.19, 0.055, 0.088, 0.933, -0.051, 189.6), #(-0.242, -0.193, 0.086, 0.112, 0.895, -0.326, 88.15), #(-0.245, -0.196, 0.132, 0.102, 0.806, -0.555, 45.22), #(-0.244, -0.094, 0.041, 0.071, 0.974, 0.194, 326.7)), #(#(-0.246, -0.178, 0.04, 0.076, 0.952, 0.111, 254.9), #(-0.242, -0.18, 0.055, 0.083, 0.943, -0.017, 202.4), #(-0.241, -0.184, 0.083, 0.104, 0.914, -0.256, 107.8), #(-0.244, -0.188, 0.127, 0.101, 0.808, -0.531, 54.32), #(-0.244, -0.085, 0.043, 0.069, 0.974, 0.197, 336.0)), #(#(-0.245, -0.169, 0.041, 0.076, 0.959, 0.116, 258.3), #(-0.241, -0.171, 0.055, 0.079, 0.954, 0.015, 214.0), #(-0.24, -0.175, 0.081, 0.096, 0.935, -0.18, 128.4), #(-0.243, -0.18, 0.122, 0.098, 0.814, -0.496, 65.77), #(-0.243, -0.075, 0.045, 0.067, 0.973, 0.202, 346.5)), #(#(-0.244, -0.159, 0.042, 0.075, 0.966, 0.123, 262.3), #(-0.241, -0.161, 0.055, 0.075, 0.964, 0.044, 224.6), #(-0.239, -0.166, 0.079, 0.087, 0.952, -0.107, 150.9), #(-0.242, -0.172, 0.117, 0.094, 0.824, -0.452, 79.27), #(-0.242, -0.065, 0.047, 0.065, 0.973, 0.208, 358.3)), #(#(-0.243, -0.149, 0.043, 0.073, 0.974, 0.133, 266.8), #(-0.24, -0.152, 0.055, 0.071, 0.975, 0.073, 234.7), #(-0.238, -0.156, 0.078, 0.078, 0.968, -0.041, 171.8), #(-0.241, -0.164, 0.112, 0.09, 0.836, -0.4, 94.45), #(-0.242, -0.055, 0.049, 0.063, 0.972, 0.213, 366.9)), #(#(-0.243, -0.14, 0.044, 0.072, 0.982, 0.146, 271.9), #(-0.239, -0.142, 0.056, 0.068, 0.986, 0.103, 244.5), #(-0.238, -0.146, 0.077, 0.071, 0.984, 0.022, 190.9), #(-0.24, -0.155, 0.108, 0.085, 0.851, -0.342, 110.9), #(-0.241, -0.046, 0.051, 0.063, 0.972, 0.216, 371.1)), #(#(-0.242, -0.13, 0.046, 0.07, 0.982, 0.149, 280.5), #(-0.238, -0.132, 0.057, 0.066, 0.987, 0.115, 256.8), #(-0.237, -0.137, 0.078, 0.066, 0.994, 0.067, 209.9), #(-0.24, -0.147, 0.105, 0.079, 0.867, -0.28, 128.2), #(-0.24, -0.036, 0.053, 0.063, 0.971, 0.219, 375.5)), #(#(-0.241, -0.12, 0.047, 0.068, 0.981, 0.153, 290.0), #(-0.238, -0.122, 0.058, 0.064, 0.987, 0.124, 270.2), #(-0.236, -0.127, 0.078, 0.064, 0.992, 0.083, 230.4), #(-0.239, -0.138, 0.102, 0.074, 0.881, -0.223, 146.1), #(-0.24, -0.026, 0.056, 0.063, 0.97, 0.223, 380.0)), #(#(-0.241, -0.11, 0.049, 0.066, 0.981, 0.158, 300.3), #(-0.237, -0.112, 0.059, 0.062, 0.986, 0.132, 284.2), #(-0.236, -0.117, 0.079, 0.061, 0.99, 0.098, 251.1), #(-0.238, -0.129, 0.1, 0.069, 0.886, -0.188, 165.3), #(-0.239, -0.017, 0.058, 0.063, 0.97, 0.227, 384.7)), #(#(-0.24, -0.1, 0.051, 0.064, 0.98, 0.164, 311.4), #(-0.237, -0.102, 0.061, 0.06, 0.985, 0.142, 298.8), #(-0.235, -0.107, 0.08, 0.059, 0.988, 0.113, 272.0), #(-0.237, -0.121, 0.098, 0.064, 0.89, -0.156, 184.9), #(-0.238, -0.007, 0.06, 0.063, 0.969, 0.232, 389.4)))

fn SetObjectRotation obj rx ry rz =
(
-- Reset the object's transformation matrix so that
-- it only includes position and scale information.
-- Doing this clears out any previous object rotation.
local translateMat = transMatrix obj.transform.pos
local scaleMat = scaleMatrix obj.transform.scale
obj.transform = scaleMat * translateMat

-- Perform each axis rotation individually
rotate obj (angleaxis rx [1,0,0])
rotate obj (angleaxis ry [0,1,0])
rotate obj (angleaxis rz [0,0,1])
)
--make empty array for tubes
extrudeMatr = #()
for i = 1 to ntubes do extrudeMatr[i] = 0

--make init circles
for j = 1 to 5 do--ntubes do 
(
    b=Circle radius:10 pos:[(tubeMatr[1][j][1] )*1000, (tubeMatr[1][j][2] )*1000,(tubeMatr[1][j][3] )*1000] isSelected:on
    convertTo b Editable_Poly
    SetObjectRotation b 0 (acos (tubeMatr[1][j][6] as float))  (atan2 (tubeMatr[1][j][5] as float)  (tubeMatr[1][j][4] as float))
    extrudeMatr[j]=b
)

--length of step
stepVec=#(tubeMatr[2][1][1]- tubeMatr[1][1][1] , tubeMatr[2][1][2] - tubeMatr[1][1][2], tubeMatr[2][1][3] - tubeMatr[1][1][3])
stepLength= sqrt (stepVec[1]^2+stepVec[2]^2+stepVec[2]^2)


--make tubes

diffAng=#()
for i = 1 to nsteps-1 do 
(
    for j = 1 to 5 do--ntubes do 
    (

        extrudeMatr[j].EditablePoly.SetSelection #Face #{1}
        extrudeMatr[j].extrudeFaces 5
        update extrudeMatr[j]
     -- I change the rotation of the faces based on the difference between angles of two vectors. This is the point I'm less confident. 
        diffAng[i]=#((atan2 tubeMatr[i+1][j][5]  tubeMatr[i+1][j][4]) - (atan2 (tubeMatr[i][j][5])  (tubeMatr[i][j][4] )) ,  (acos (tubeMatr[i+1][j][6] ))-(acos (tubeMatr[i][j][6] )))  

        extrudeMatr[j].EditablePoly.SetSelection #Face #{1}
--next chunk performs the rotation of the face. I found it on one of the cg forums and it seems legit. Though, I might use it wrong
        (
        angle =diffAng[i][1]
        selected_faces = (polyOp.getFaceSelection extrudeMatr[j]) as array
        center_face = polyOp.getFaceCenter extrudeMatr[j] selected_faces[1]
        transform_mat = matrixFromNormal (polyOp.getFaceNormal extrudeMatr[j] selected_faces[1])
        transform_mat.row4 = center_face --move TM to center of polygon

        face_vertices = (polyOp.getVertsUsingFace extrudeMatr[j] #selection) as array

        for v in face_vertices do
        (
        in coordsys transform_mat --get vertex in Normal's TM coordinates
        vertex_position = (polyOp.getVert extrudeMatr[j] v)
        -- create a Rotation TM, transform in the Normal's TM:
        RotateZ = (rotateZMatrix angle) * transform_mat
        -- finally, set the vertex to the position transformed by the rotation matrix
        polyOp.setVert extrudeMatr[j] v (vertex_position * RotateZ)
        )
        angle = diffAng[i][2]
        for v in face_vertices do
        (
        in coordsys transform_mat --get vertex in Normal's TM coordinates
        vertex_position = (polyOp.getVert extrudeMatr[j] v)
        -- create a Rotation TM, transform in the Normal's TM:
        RotateZ = (rotateYMatrix angle) * transform_mat
        -- finally, set the vertex to the position transformed by the rotation matrix
        polyOp.setVert extrudeMatr[j] v (vertex_position * RotateZ)
        )

        )

    )
)

Also I tried to do that with splines, but there after rotation of the face all went to hell (since extrusion was relative to the circle orientation), so I dropped that method. However, splines here show, where the tube is supposed to go (care about shape, not length):

    --first, same matrix
    tubeMatr = #(#(#(-0.252, -0.282, 0.02, 0.025, 0.953, 0.302, 181.2), #(-0.252, -0.282, 0.074, 0.045, 0.957, -0.183, 42.16), #(-0.252, -0.282, 0.128, 0.045, 0.927, -0.341, 25.83), #(-0.252, -0.282, 0.182, 0.013, 0.903, -0.407, 23.73), #(-0.252, -0.191, 0.02, 0.062, 0.955, 0.282, 317.7)), #(#(-0.252, -0.272, 0.023, 0.03, 0.952, 0.274, 192.8), #(-0.251, -0.272, 0.072, 0.06, 0.945, -0.195, 51.41), #(-0.251, -0.273, 0.124, 0.056, 0.916, -0.361, 27.39), #(-0.252, -0.273, 0.178, 0.026, 0.892, -0.427, 24.9), #(-0.251, -0.181, 0.023, 0.069, 0.955, 0.25, 309.6)), #(#(-0.251, -0.263, 0.026, 0.036, 0.95, 0.245, 203.5), #(-0.251, -0.263, 0.07, 0.073, 0.934, -0.204, 62.15), #(-0.251, -0.263, 0.121, 0.068, 0.906, -0.381, 29.05), #(-0.251, -0.264, 0.173, 0.039, 0.88, -0.447, 26.13), #(-0.25, -0.172, 0.025, 0.074, 0.958, 0.226, 304.1)), #(#(-0.251, -0.253, 0.028, 0.044, 0.947, 0.216, 213.4), #(-0.25, -0.253, 0.068, 0.084, 0.924, -0.21, 74.34), #(-0.25, -0.254, 0.117, 0.08, 0.895, -0.401, 30.81), #(-0.251, -0.255, 0.169, 0.051, 0.87, -0.467, 27.44), #(-0.25, -0.162, 0.028, 0.077, 0.961, 0.21, 300.6)), #(#(-0.25, -0.244, 0.03, 0.051, 0.943, 0.188, 223.0), #(-0.249, -0.244, 0.066, 0.094, 0.915, -0.214, 87.96), #(-0.249, -0.245, 0.113, 0.092, 0.885, -0.423, 32.69), #(-0.25, -0.246, 0.164, 0.063, 0.859, -0.486, 28.84), #(-0.249, -0.153, 0.03, 0.079, 0.965, 0.199, 298.8)), #(#(-0.25, -0.234, 0.032, 0.06, 0.939, 0.16, 232.4), #(-0.248, -0.235, 0.064, 0.103, 0.907, -0.215, 102.9), #(-0.248, -0.236, 0.109, 0.106, 0.875, -0.445, 34.7), #(-0.25, -0.238, 0.159, 0.075, 0.849, -0.505, 30.33), #(-0.248, -0.143, 0.032, 0.08, 0.971, 0.193, 298.3)), #(#(-0.249, -0.225, 0.034, 0.068, 0.934, 0.133, 241.8), #(-0.247, -0.226, 0.062, 0.11, 0.9, -0.214, 119.2), #(-0.247, -0.228, 0.104, 0.12, 0.865, -0.468, 36.87), #(-0.249, -0.229, 0.154, 0.087, 0.84, -0.525, 31.93), #(-0.247, -0.133, 0.034, 0.079, 0.973, 0.19, 301.0)), #(#(-0.249, -0.216, 0.035, 0.073, 0.933, 0.115, 246.9), #(-0.246, -0.217, 0.06, 0.111, 0.9, -0.192, 138.0), #(-0.246, -0.219, 0.1, 0.132, 0.857, -0.486, 40.28), #(-0.248, -0.221, 0.149, 0.098, 0.83, -0.544, 33.64), #(-0.247, -0.124, 0.035, 0.077, 0.973, 0.19, 305.7)), #(#(-0.248, -0.206, 0.036, 0.075, 0.937, 0.11, 247.8), #(-0.245, -0.208, 0.058, 0.101, 0.912, -0.136, 158.1), #(-0.245, -0.211, 0.095, 0.126, 0.866, -0.443, 54.04), #(-0.247, -0.213, 0.144, 0.101, 0.819, -0.558, 35.67), #(-0.246, -0.114, 0.037, 0.075, 0.974, 0.19, 311.5)), #(#(-0.247, -0.197, 0.037, 0.076, 0.941, 0.108, 249.5), #(-0.244, -0.199, 0.056, 0.094, 0.923, -0.09, 175.0), #(-0.244, -0.202, 0.09, 0.119, 0.878, -0.389, 70.1), #(-0.246, -0.204, 0.138, 0.102, 0.809, -0.566, 38.7), #(-0.245, -0.104, 0.039, 0.073, 0.974, 0.191, 318.5)), #(#(-0.246, -0.188, 0.039, 0.076, 0.947, 0.108, 251.9), #(-0.243, -0.19, 0.055, 0.088, 0.933, -0.051, 189.6), #(-0.242, -0.193, 0.086, 0.112, 0.895, -0.326, 88.15), #(-0.245, -0.196, 0.132, 0.102, 0.806, -0.555, 45.22), #(-0.244, -0.094, 0.041, 0.071, 0.974, 0.194, 326.7)), #(#(-0.246, -0.178, 0.04, 0.076, 0.952, 0.111, 254.9), #(-0.242, -0.18, 0.055, 0.083, 0.943, -0.017, 202.4), #(-0.241, -0.184, 0.083, 0.104, 0.914, -0.256, 107.8), #(-0.244, -0.188, 0.127, 0.101, 0.808, -0.531, 54.32), #(-0.244, -0.085, 0.043, 0.069, 0.974, 0.197, 336.0)), #(#(-0.245, -0.169, 0.041, 0.076, 0.959, 0.116, 258.3), #(-0.241, -0.171, 0.055, 0.079, 0.954, 0.015, 214.0), #(-0.24, -0.175, 0.081, 0.096, 0.935, -0.18, 128.4), #(-0.243, -0.18, 0.122, 0.098, 0.814, -0.496, 65.77), #(-0.243, -0.075, 0.045, 0.067, 0.973, 0.202, 346.5)), #(#(-0.244, -0.159, 0.042, 0.075, 0.966, 0.123, 262.3), #(-0.241, -0.161, 0.055, 0.075, 0.964, 0.044, 224.6), #(-0.239, -0.166, 0.079, 0.087, 0.952, -0.107, 150.9), #(-0.242, -0.172, 0.117, 0.094, 0.824, -0.452, 79.27), #(-0.242, -0.065, 0.047, 0.065, 0.973, 0.208, 358.3)), #(#(-0.243, -0.149, 0.043, 0.073, 0.974, 0.133, 266.8), #(-0.24, -0.152, 0.055, 0.071, 0.975, 0.073, 234.7), #(-0.238, -0.156, 0.078, 0.078, 0.968, -0.041, 171.8), #(-0.241, -0.164, 0.112, 0.09, 0.836, -0.4, 94.45), #(-0.242, -0.055, 0.049, 0.063, 0.972, 0.213, 366.9)), #(#(-0.243, -0.14, 0.044, 0.072, 0.982, 0.146, 271.9), #(-0.239, -0.142, 0.056, 0.068, 0.986, 0.103, 244.5), #(-0.238, -0.146, 0.077, 0.071, 0.984, 0.022, 190.9), #(-0.24, -0.155, 0.108, 0.085, 0.851, -0.342, 110.9), #(-0.241, -0.046, 0.051, 0.063, 0.972, 0.216, 371.1)), #(#(-0.242, -0.13, 0.046, 0.07, 0.982, 0.149, 280.5), #(-0.238, -0.132, 0.057, 0.066, 0.987, 0.115, 256.8), #(-0.237, -0.137, 0.078, 0.066, 0.994, 0.067, 209.9), #(-0.24, -0.147, 0.105, 0.079, 0.867, -0.28, 128.2), #(-0.24, -0.036, 0.053, 0.063, 0.971, 0.219, 375.5)), #(#(-0.241, -0.12, 0.047, 0.068, 0.981, 0.153, 290.0), #(-0.238, -0.122, 0.058, 0.064, 0.987, 0.124, 270.2), #(-0.236, -0.127, 0.078, 0.064, 0.992, 0.083, 230.4), #(-0.239, -0.138, 0.102, 0.074, 0.881, -0.223, 146.1), #(-0.24, -0.026, 0.056, 0.063, 0.97, 0.223, 380.0)), #(#(-0.241, -0.11, 0.049, 0.066, 0.981, 0.158, 300.3), #(-0.237, -0.112, 0.059, 0.062, 0.986, 0.132, 284.2), #(-0.236, -0.117, 0.079, 0.061, 0.99, 0.098, 251.1), #(-0.238, -0.129, 0.1, 0.069, 0.886, -0.188, 165.3), #(-0.239, -0.017, 0.058, 0.063, 0.97, 0.227, 384.7)), #(#(-0.24, -0.1, 0.051, 0.064, 0.98, 0.164, 311.4), #(-0.237, -0.102, 0.061, 0.06, 0.985, 0.142, 298.8), #(-0.235, -0.107, 0.08, 0.059, 0.988, 0.113, 272.0), #(-0.237, -0.121, 0.098, 0.064, 0.89, -0.156, 184.9), #(-0.238, -0.007, 0.06, 0.063, 0.969, 0.232, 389.4)))
--make empty array for tubes
extrudeMatr = #()
for i = 1 to ntubes do extrudeMatr[i] = 0

--make splines
for i = 1 to nsteps-1 do 
(
    for j = 1 to 5 do--ntubes do 
    (

        PointA=[(tubeMatr[i][j][1] as float)*1000, (tubeMatr[i][j][2] as float)*1000,(tubeMatr[i][j][3] as float)*1000]
        PointB=[(tubeMatr[i+1][j][1] as float)*1000, (tubeMatr[i+1][j][2] as float)*1000,(tubeMatr[i+1][j][3] as float)*1000]
        ss = SplineShape pos:PointA
        addNewSpline ss
        addKnot ss 1 #corner #line PointA
        addKnot ss 1 #corner #line PointB
        updateShape ss

    )
)

Sorry for such a long question, just I'm really stuck here.

1 Answers1

0

Just curious, what's the axis order here? Looks kinda wonky when I assume its XYZ:

struct tubePoint
(
    data,
    pos = 1000 * [data[1], data[2], data[3]],
    dir = [data[4], data[5], data[6]],
    radius = data[7] / 2d0
)

fn updateTM tm rot =
(
    tm.row1 *= rot
    tm.row2 *= rot
    tm.row3 *= rot
)

fn getRotQuat vec1 vec2 =
    quat (acos (dot vec1 vec2)) (normalize (cross vec1 vec2))

fn getTMAlongPath pt prevTM =
(
    updateTM prevTM (getRotQuat pt.dir prevTM.row3)
    prevTM * transMatrix pt.pos
)

fn addQuad pt1 pt2 pt3 pt4 &faces =
(
    append faces [pt1, pt4, pt3]
    append faces [pt3, pt2, pt1]
)

fn addNGonPoints n radius ngonTM &vertList clockwise:false =
(
    local angle = 360d0 / n * (if clockwise then 1 else -1)
    local vertCount = vertList.count

    for i = 1 to n collect
    (
        append vertList ([radius * sin (i * angle), radius * cos (i * angle), 0] * ngonTM)
        vertCount + i
    )
)

fn makeQuadStrip pts1 pts2 count &faceList closed:false =
(
    if closed do count -= 1
    for offset = 1 to count do
        addQuad pts1[offset] pts1[offset + 1] pts2[offset + 1] pts2[offset] &faceList

    if closed do addQuad pts1[count + 1] pts1[1] pts2[1] pts2[count + 1] &faceList
)

fn constructTube pts sides vertList:#() faceList:#() =
(
    local firstPoint = pts[1]
    local prevTM = arbAxis firstPoint.dir
    local prevRow = addNGonPoints sides firstPoint.radius (prevTM * transMatrix firstPoint.pos) &vertList clockwise:true

    for i = 2 to pts.count do
    (
        local nextPoint = pts[i]
        local nextRow = addNGonPoints sides nextPoint.radius (getTMAlongPath nextPoint prevTM) &vertList clockwise:true

        makeQuadStrip prevRow nextRow sides &faceList closed:true

        prevRow = nextRow
    )

    local tubeMesh = Mesh vertices:vertList faces:faceList
    for face in tubeMesh.faces do setEdgeVis tubeMesh face.index 3 false
    for face = 1 to faceList.count do setFaceSmoothGroup tubeMesh face (1 + int(mod ((face - 1) / (2 * sides)) 2))
)

for tubePts in tubeMatr do constructTube (for pt in tubePts collect tubePoint data:pt) 16

In order to get a rearranged list of data (i.e. #(#(1, 1, 1), #(2, 2, 2), #(3, 3, 3), #(4, 4, 4), #(5, 5, 5)) instead of #(#(1, 2, 3, 4, 5), #(1, 2, 3, 4, 5), #(1, 2, 3, 4, 5)), replace the last line with these two:

transposedTubeMatr = for i = 1 to tubeMatr[1].count collect for j = 1 to tubeMatr.count collect tubeMatr[j][i]
for tubePts in transposedTubeMatr do constructTube (for pt in tubePts collect tubePoint data:pt) 16
Swordslayer
  • 2,061
  • 1
  • 13
  • 15
  • Could you please tell me how to run the code? I tried with assigning the matrix of points to pt and then run the code, but for some reason it seems to convert values to strings or something and then shows error: -- Error occurred in pt loop; filename: ; position: 78; line: 4 -- Frame: -- pt: #("-0.252", "-0.282", "0.020", "-0.424", "-0.185", "-0.105", "22.360") -- called in tubePts loop; filename: ; position: 1986; line: 72 -- Frame: -- tubePts: #(#("-0.252", "-0.282", "0.020", "-0.424", "-0.185", "-0.105", "22.360"), ...) -- Unable to convert: "-0.252" to type: Float – Tatiana Kartashova May 11 '16 at 12:53
  • Thank you very much for you reply! – Tatiana Kartashova May 11 '16 at 12:54
  • _>>Just curious, what's the axis order here? Looks kinda wonky when I assume its XYZ:_ Unfortunately, I can't say that I fully understand the question. I didn't (conciously) do anything with the axis, so should be default XYZ. – Tatiana Kartashova May 11 '16 at 12:55
  • I used your original tubeMatr from the first post, where the points were already float values... It doesn't do any typecast. As for the axis order, some software packages use a different one, that's why I was asking (that, and because the resulting shapes looked kinda weird to me). – Swordslayer May 11 '16 at 12:55
  • Huh, indeed if I just copy the matrix from here, it works. I guess, I messed up somewhere with conversion. Anyway, one reason why it looks strange is because there are 5 tubes and 20 steps, not 20 tubes of 5 steps. As soon as I find where I made a error with making matrix, I'll give you (and see if the code works, because it looks great!) a rearranged one, where tube number will be the first index. – Tatiana Kartashova May 11 '16 at 13:24
  • I've also added different smoothing for alternating rings (the line with `setFaceSmoothGroup` in it). Note also the 'magic number' at the very end, which is the number of sides - 16 here, ramp it up as needed. – Swordslayer May 11 '16 at 13:55
  • Yaay, with the last edit it works perfectly! (to see tubes better, I scale the width) Thank you very much!! – Tatiana Kartashova May 11 '16 at 14:03
  • My pleasure, glad it does what you expected it to do. – Swordslayer May 11 '16 at 14:06