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.