diff --git a/doc/ru/vcm.md b/doc/ru/vcm.md index 2a86fc990..8943a19a0 100644 --- a/doc/ru/vcm.md +++ b/doc/ru/vcm.md @@ -36,8 +36,12 @@ - `c` - точка С. Пример: `c (1,1,0)` - `uv` - нормализованные текстурные координаты точек (6 чисел, по 2 на точку). Пример: `uv (0,0, 1,0, 1,1)` - `texture` - отображаемая текстура. По-умолчанию: `$0`. Пример: `texture "blocks:sand"` +- `region` - UV регион в границах выбранной текстуры, определяется позициями противоположных углов квадрата нормализованных текстурных координат. Пример: `region (0,0,1,1)` +- `region-scale` вектор-множитель для UV региона. Пример: `region-scale (0.5,1)` - `shading` определяет возможность затенения на примитиве. Пример: `shading off` +Текстурные координаты по-умолчанию не зависят от формы из размера, в отличие от других примитивов. + ### Свойства `rect` Примитив описывает параллелограмм через векторы right и up. diff --git a/src/coders/vcm.cpp b/src/coders/vcm.cpp index c797d8566..5bf54ee99 100644 --- a/src/coders/vcm.cpp +++ b/src/coders/vcm.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "xml.hpp" #include "util/stringutil.hpp" @@ -76,32 +77,35 @@ static void perform_triangle(const xmlelement& root, model::Model& model) { auto pointB = root.attr("b").asVec3(); auto pointC = root.attr("c").asVec3(); - float uvs[6] {0, 0, 1, 0, 1, 1}; + glm::vec2 uvs[3] {{0, 0}, {1, 0}, {1, 1}}; bool shading = true; if (root.has("shading")) { shading = to_boolean(root.attr("shading")); } - if (root.has("uv")) { - root.attr("uv").asNumbers(uvs, sizeof(uvs) / sizeof(float)); - } - + glm::vec3 ba = pointB - pointA; glm::vec3 ca = pointC - pointA; glm::vec3 normal = glm::normalize(glm::cross(ba, ca)); - + + if (root.has("uv")) { + root.attr("uv").asNumbers(glm::value_ptr(uvs[0]), 6); + } else { + UVRegion region {}; + if (root.has("region")) { + region.set(root.attr("region").asVec4()); + } + if (root.has("region-scale")) { + region.scale(root.attr("region-scale").asVec2()); + } + for (auto& uv : uvs) { + uv = region.apply(uv); + } + } + std::string texture = root.attr("texture", "$0").getText(); auto& mesh = model.addMesh(texture, shading); - - mesh.addTriangle( - pointA, - pointB, - pointC, - normal, - {uvs[0], uvs[1]}, - {uvs[2], uvs[3]}, - {uvs[4], uvs[5]} - ); + mesh.addTriangle(pointA, pointB, pointC, normal, uvs[0], uvs[1], uvs[2]); } static void perform_box(const xmlelement& root, model::Model& model) {