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

◆ mill_on_host()

MAYAFLUX_API Kakshya::VertexLayout MayaFlux::Portal::Graphics::mill_on_host ( std::span< const uint8_t >  src,
const Kakshya::VertexLayout layout,
std::span< const DrawRun runs,
const MillSpec spec,
const MillView view,
std::vector< uint8_t > &  dst 
)

Host equivalent of PrimitiveMill::mill, over raw bytes.

Parameters
srcSource vertex bytes. Must be four byte aligned.
layoutDescribes src. The result carries the same attributes.
runsSpans to mill, in output order.
specShaping parameters, as for the device path.
viewViewpoint, as for the device path.
dstResized to hold the result.
Returns
Layout describing dst, which is layout with a new vertex_count.

Exists so the kernel has an oracle: identical spans, spec and view must produce identical bytes on both paths. Secondarily a route for a caller with no compute queue available. Not a general geometry utility, and not intended for per-frame use at scale.

Definition at line 864 of file PrimitiveMill.cpp.

871{
872 auto result = layout;
873 result.vertex_count = 0;
874 dst.clear();
875
876 MillOffsets off;
877 if (!offsets_from(layout, off)) {
878 return result;
879 }
880
881 std::vector<uint32_t> prefix;
882 build_prefix(runs, prefix);
883 const uint32_t total = prefix.empty() ? 0U : prefix.back();
884 if (total == 0) {
885 return result;
886 }
887
888 dst.assign(static_cast<size_t>(total) * layout.stride_bytes, 0);
889 result.vertex_count = total;
890
891 const HostRecords rec {
892 .src = reinterpret_cast<const uint32_t*>(src.data()),
893 .dst = reinterpret_cast<uint32_t*>(dst.data()),
894 .stride_words = off.stride_words
895 };
896
897 const bool world_plane = spec.ribbon == MillSpec::Ribbon::WorldPlane;
898 const uint32_t scalar_offset = spec.use_vertex_extent ? off.scalar : ABSENT;
899
900 for (size_t r = 0; r < runs.size(); ++r) {
901 const auto& run = runs[r];
902 const uint32_t emitted = prefix[r + 1] - prefix[r];
903 const uint32_t base = prefix[r];
904 const uint32_t voff = run.vertex_offset;
905
906 for (uint32_t local = 0; local < emitted; ++local) {
907 const uint32_t out = base + local;
908
909 if (run.topology == PrimitiveTopology::TRIANGLE_LIST) {
910 rec.copy_vertex(out, voff + local);
911 continue;
912 }
913
914 if (run.topology == PrimitiveTopology::TRIANGLE_STRIP
915 || run.topology == PrimitiveTopology::TRIANGLE_FAN) {
916 const uint32_t tri = local / 3U;
917 const uint32_t c = local - tri * 3U;
918 uint32_t a = 0;
919 uint32_t b1 = tri + 1U;
920 uint32_t b2 = tri + 2U;
921 if (run.topology == PrimitiveTopology::TRIANGLE_STRIP) {
922 a = tri;
923 if ((tri & 1U) == 1U) {
924 std::swap(a, b1);
925 }
926 }
927 const uint32_t pick = c == 0U ? a : (c == 1U ? b1 : b2);
928 rec.copy_vertex(out, voff + pick);
929 continue;
930 }
931
932 const uint32_t corner = local % 6U;
933 const uint32_t quad = local / 6U;
934
935 if (run.topology == PrimitiveTopology::POINT_LIST) {
936 const uint32_t s = voff + quad;
937 const glm::vec3 p = rec.read_pos(s, off.position);
938 const float h = rec.read_extent(s, scalar_offset, spec.fallback_extent)
939 * spec.point_scale * 0.5F;
940
941 glm::vec3 rx;
942 glm::vec3 ry;
943 if (world_plane) {
944 rx = glm::vec3(h, 0.0F, 0.0F);
945 ry = glm::vec3(0.0F, h, 0.0F);
946 } else {
947 const glm::vec3 n = host_view_normal(p, view.eye);
948 const glm::vec3 up = std::abs(n.y) < 0.99F
949 ? glm::vec3(0.0F, 1.0F, 0.0F)
950 : glm::vec3(1.0F, 0.0F, 0.0F);
951 rx = glm::normalize(glm::cross(up, n)) * h;
952 ry = glm::normalize(glm::cross(n, rx)) * h;
953 }
954
955 glm::vec3 o;
956 glm::vec2 uv;
957 switch (corner) {
958 case 1:
959 o = rx - ry;
960 uv = { 1.0F, 0.0F };
961 break;
962 case 2:
963 case 4:
964 o = rx + ry;
965 uv = { 1.0F, 1.0F };
966 break;
967 case 5:
968 o = -rx + ry;
969 uv = { 0.0F, 1.0F };
970 break;
971 default:
972 o = -rx - ry;
973 uv = { 0.0F, 0.0F };
974 break;
975 }
976
977 rec.copy_vertex(out, s);
978 rec.write_pos(out, off.position, p + o);
979 if (spec.synthesize_uv) {
980 rec.write_uv(out, off.uv, uv);
981 }
982 continue;
983 }
984
985 const uint32_t s0 = run.topology == PrimitiveTopology::LINE_LIST
986 ? voff + quad * 2U
987 : voff + quad;
988 const uint32_t s1 = s0 + 1U;
989
990 const glm::vec3 p0 = rec.read_pos(s0, off.position);
991 const glm::vec3 p1 = rec.read_pos(s1, off.position);
992 const glm::vec3 d = p1 - p0;
993
994 if (glm::length(d) < 1e-6F) {
995 rec.write_pos(out, off.position, p0);
996 continue;
997 }
998
999 const float h0 = rec.read_extent(s0, scalar_offset, spec.fallback_extent)
1000 * spec.width_scale * 0.5F;
1001 const float h1 = rec.read_extent(s1, scalar_offset, spec.fallback_extent)
1002 * spec.width_scale * 0.5F;
1003
1004 const glm::vec3 e0 = host_side_at(
1005 p0, d, view.eye, h0, world_plane);
1006 const glm::vec3 e1 = host_side_at(
1007 p1, d, view.eye, h1, world_plane);
1008
1009 glm::vec3 pos;
1010 uint32_t pick = s0;
1011 glm::vec2 uv;
1012 switch (corner) {
1013 case 1:
1014 pos = p0 + e0;
1015 uv = { 0.0F, 0.0F };
1016 break;
1017 case 2:
1018 case 4:
1019 pos = p1 + e1;
1020 pick = s1;
1021 uv = { 1.0F, 0.0F };
1022 break;
1023 case 5:
1024 pos = p1 - e1;
1025 pick = s1;
1026 uv = { 1.0F, 1.0F };
1027 break;
1028 default:
1029 pos = p0 - e0;
1030 uv = { 0.0F, 1.0F };
1031 break;
1032 }
1033
1034 rec.copy_vertex(out, pick);
1035 rec.write_pos(out, off.position, pos);
1036 if (spec.synthesize_uv) {
1037 rec.write_uv(out, off.uv, uv);
1038 }
1039 }
1040 }
1041
1042 return result;
1043}
uint32_t h
Definition InkPress.cpp:29
uint32_t stride_words
uint32_t * dst
const uint32_t * src
uint32_t total
uint32_t scalar_offset
uint32_t uv
size_t a
std::vector< float > * out
void run()
Definition main.cpp:22
uint32_t stride_bytes
Total bytes per vertex (stride in Vulkan terms) e.g., 3 floats (position) + 3 floats (normal) = 24 by...
uint32_t vertex_count
Total number of vertices in this buffer.
bool synthesize_uv
Write 0..1 across each ribbon and quad rather than copying source.
float fallback_extent
Extent used when the layout carries no scalar attribute.
float width_scale
World units of total ribbon width per unit of a vertex's scalar.
bool use_vertex_extent
Take ribbon width and point size from each vertex's own scalar (LineVertex::thickness,...
float point_scale
World units per unit of a vertex's own size, on point spans.

References a, dst, MayaFlux::Portal::Graphics::MillView::eye, MayaFlux::Portal::Graphics::MillSpec::fallback_extent, h, LINE_LIST, out, POINT_LIST, MayaFlux::Portal::Graphics::MillSpec::point_scale, MayaFlux::Portal::Graphics::MillSpec::ribbon, run(), scalar_offset, src, MayaFlux::Kakshya::VertexLayout::stride_bytes, stride_words, MayaFlux::Portal::Graphics::MillSpec::synthesize_uv, total, TRIANGLE_FAN, TRIANGLE_LIST, TRIANGLE_STRIP, MayaFlux::Portal::Graphics::MillSpec::use_vertex_extent, uv, MayaFlux::Kakshya::VertexLayout::vertex_count, MayaFlux::Portal::Graphics::MillSpec::width_scale, and MayaFlux::Portal::Graphics::MillSpec::WorldPlane.

+ Here is the call graph for this function: