Generate a subdivided flat grid in the XZ plane.
Vertices lie at Y = 0. U maps to X, V maps to Z. UV covers [0,1] across the full extent. Normals point along +Y throughout.
823{
824 cols = std::max(cols, 1U);
825 rows = std::max(rows, 1U);
826
827 const glm::vec3 n = glm::normalize(normal);
828 glm::vec3 u;
829 if (std::abs(n.y) < 0.9F) {
830 u = glm::normalize(glm::cross(n, glm::vec3(0.0F, 1.0F, 0.0F)));
831 } else {
832 u = glm::normalize(glm::cross(n, glm::vec3(1.0F, 0.0F, 0.0F)));
833 }
834 const glm::vec3 v = glm::normalize(glm::cross(u, n));
835
836 const float half_x = extent_x * 0.5F;
837 const float half_z = extent_z * 0.5F;
838
839 std::vector<Kakshya::MeshVertex> verts;
840 std::vector<uint32_t> indices;
841 verts.reserve(uint32_t(2 * (cols + 1) * (rows + 1)));
842 indices.reserve(uint32_t(2 * cols * rows * 6));
843
844 for (uint32_t row = 0; row <= rows; ++row) {
845 const float fv = static_cast<float>(row) / static_cast<float>(rows);
846 for (uint32_t col = 0; col <= cols; ++col) {
847 const float fu = static_cast<float>(col) / static_cast<float>(cols);
848 const glm::vec3 p = center
849 + u * glm::mix(-half_x, half_x, fu)
850 + v * glm::mix(-half_z, half_z, fv);
851 verts.push_back({
852 .position = p,
853 .uv = { fu, 1.0F - fv },
854 .normal = n,
855 });
856 }
857 }
858
859 const uint32_t stride = cols + 1;
860 const auto vert_count = static_cast<uint32_t>(verts.size());
861
862 for (uint32_t row = 0; row < rows; ++row) {
863 for (uint32_t col = 0; col < cols; ++col) {
864 const uint32_t
a = row * stride + col;
865 const uint32_t
b =
a + 1;
866 const uint32_t c =
a + stride;
867 const uint32_t d = c + 1;
868 indices.insert(indices.end(), {
a,
b, c,
b, d, c });
869 }
870 }
871
872 for (uint32_t row = 0; row <= rows; ++row) {
873 const float fv = static_cast<float>(row) / static_cast<float>(rows);
874 for (uint32_t col = 0; col <= cols; ++col) {
875 const float fu = static_cast<float>(col) / static_cast<float>(cols);
876 const glm::vec3 p = center
877 + u * glm::mix(-half_x, half_x, fu)
878 + v * glm::mix(-half_z, half_z, fv);
879 verts.push_back({
880 .position = p,
881 .uv = { fu, 1.0F - fv },
882 .normal = -n,
883 });
884 }
885 }
886
887 for (uint32_t row = 0; row < rows; ++row) {
888 for (uint32_t col = 0; col < cols; ++col) {
889 const uint32_t
a = vert_count + row * stride + col;
890 const uint32_t
b =
a + 1;
891 const uint32_t c =
a + stride;
892 const uint32_t d = c + 1;
893 indices.insert(indices.end(), { a, c, b, b, c, d });
894 }
895 }
896
897 auto data = Kakshya::MeshData::empty();
898 Kakshya::MeshInsertion ins(data.vertex_variant, data.index_variant);
899 ins.insert_flat(
900 std::span<const uint8_t>(reinterpret_cast<const uint8_t*>(verts.data()),
901 verts.size() * sizeof(Kakshya::MeshVertex)),
902 std::span<const uint32_t>(indices),
903 Kakshya::VertexLayout::for_meshes(sizeof(Kakshya::MeshVertex)));
904 data.layout = Kakshya::VertexLayout::for_meshes(sizeof(Kakshya::MeshVertex));
905 data.layout.vertex_count = static_cast<uint32_t>(verts.size());
906 return data;
907}