MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ generate_tube() [2/2]

Kakshya::MeshData MayaFlux::Kinesis::generate_tube ( std::span< const glm::vec3 >  path,
const std::function< float(float)> &  radius_fn,
uint32_t  radial_segments,
bool  capped 
)

Definition at line 966 of file GeometryPrimitives.cpp.

971{
972 const uint32_t seg = std::max(radial_segments, 3U);
973 const auto n_pts = static_cast<uint32_t>(std::max<size_t>(path.size(), 2));
974
975 std::vector<Kakshya::MeshVertex> verts;
976 std::vector<uint32_t> indices;
977 verts.reserve(uint32_t(n_pts * (seg + 1) + (capped ? 2 * (seg + 1) : 0)));
978 indices.reserve(uint32_t((n_pts - 1) * seg * 6 + (capped ? 2 * seg * 3 : 0)));
979
980 glm::vec3 tangent = glm::normalize(path[1] - path[0]);
981 glm::vec3 u_axis;
982 if (std::abs(tangent.y) < 0.9F) {
983 u_axis = glm::normalize(glm::cross(tangent, glm::vec3(0.0F, 1.0F, 0.0F)));
984 } else {
985 u_axis = glm::normalize(glm::cross(tangent, glm::vec3(1.0F, 0.0F, 0.0F)));
986 }
987
988 glm::vec3 v_axis = glm::normalize(glm::cross(tangent, u_axis));
989
990 const float total_len = [&]() {
991 float l = 0.0F;
992 for (uint32_t i = 1; i < n_pts; ++i)
993 l += glm::distance(path[i], path[i - 1]);
994 return l;
995 }();
996
997 float arc = 0.0F;
998
999 for (uint32_t pi = 0; pi < n_pts; ++pi) {
1000 if (pi > 0) {
1001 const glm::vec3 new_tan = (pi + 1 < n_pts)
1002 ? glm::normalize(path[pi + 1] - path[pi - 1])
1003 : glm::normalize(path[pi] - path[pi - 1]);
1004 const glm::vec3 axis = glm::cross(tangent, new_tan);
1005 const float axis_len = glm::length(axis);
1006 if (axis_len > 1e-6F) {
1007 const float angle = std::asin(glm::clamp(axis_len, 0.0F, 1.0F));
1008 const glm::mat4 rot = glm::rotate(glm::mat4(1.0F), angle,
1009 glm::normalize(axis));
1010 u_axis = glm::vec3(rot * glm::vec4(u_axis, 0.0F));
1011 v_axis = glm::vec3(rot * glm::vec4(v_axis, 0.0F));
1012 tangent = new_tan;
1013 }
1014 arc += glm::distance(path[pi], path[pi - 1]);
1015 }
1016
1017 const float t = (total_len > 1e-6F) ? (arc / total_len) : 0.0F;
1018 const float r = radius_fn(t);
1019 const float angle_step = glm::two_pi<float>() / static_cast<float>(seg);
1020
1021 for (uint32_t s = 0; s <= seg; ++s) {
1022 const float a = static_cast<float>(s) * angle_step;
1023 const float ca = std::cos(a);
1024 const float sa = std::sin(a);
1025 const glm::vec3 radial = ca * u_axis + sa * v_axis;
1026 verts.push_back({
1027 .position = path[pi] + radial * r,
1028 .uv = { static_cast<float>(s) / static_cast<float>(seg), t },
1029 .normal = radial,
1030 });
1031 }
1032 }
1033
1034 const uint32_t ring = seg + 1;
1035 for (uint32_t pi = 0; pi < n_pts - 1; ++pi) {
1036 for (uint32_t s = 0; s < seg; ++s) {
1037 const uint32_t a = pi * ring + s;
1038 const uint32_t b = a + 1;
1039 const uint32_t c = a + ring;
1040 const uint32_t d = c + 1;
1041 indices.insert(indices.end(), { a, b, c, b, d, c });
1042 }
1043 }
1044
1045 if (capped) {
1046 for (int end = 0; end < 2; ++end) {
1047 const uint32_t ring_base = (end == 0) ? 0 : (n_pts - 1) * ring;
1048 const float t_cap = (end == 0) ? 0.0F : 1.0F;
1049 const glm::vec3 cap_nrm = (end == 0) ? -tangent : tangent;
1050 const glm::vec3 cap_pos = path[(end == 0) ? 0 : n_pts - 1];
1051
1052 const auto centre_idx = static_cast<uint32_t>(verts.size());
1053 verts.push_back({
1054 .position = cap_pos,
1055 .uv = { 0.5F, t_cap },
1056 .normal = cap_nrm,
1057 });
1058
1059 for (uint32_t s = 0; s < seg; ++s) {
1060 const uint32_t a = ring_base + s;
1061 const uint32_t b = ring_base + s + 1;
1062 if (end == 0) {
1063 indices.insert(indices.end(), { centre_idx, b, a });
1064 } else {
1065 indices.insert(indices.end(), { centre_idx, a, b });
1066 }
1067 }
1068 }
1069 }
1070
1071 auto data = Kakshya::MeshData::empty();
1072 Kakshya::MeshInsertion ins(data.vertex_variant, data.index_variant);
1073 ins.insert_flat(
1074 std::span<const uint8_t>(reinterpret_cast<const uint8_t*>(verts.data()),
1075 verts.size() * sizeof(Kakshya::MeshVertex)),
1076 std::span<const uint32_t>(indices),
1077 Kakshya::VertexLayout::for_meshes(sizeof(Kakshya::MeshVertex)));
1078 data.layout = Kakshya::VertexLayout::for_meshes(sizeof(Kakshya::MeshVertex));
1079 data.layout.vertex_count = static_cast<uint32_t>(verts.size());
1080 return data;
1081}
size_t a
size_t b
GeometryFn< float > radial(glm::vec2 center, float radius, float angle_start, float angle_end, glm::vec3 color)
Geometry function for a radial indicator in NDC space.
Definition Geometry.cpp:61

References a, b, generate_tube(), and MayaFlux::Kakshya::MeshInsertion::insert_flat().

Referenced by generate_tube().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: