Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc')
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc157
1 files changed, 157 insertions, 0 deletions
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc
new file mode 100644
index 00000000000..16814653408
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc
@@ -0,0 +1,157 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_mesh.h"
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Edit UV area stretch
+ * \{ */
+
+static void extract_edituv_stretch_area_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len);
+}
+
+BLI_INLINE float area_ratio_get(float area, float uvarea)
+{
+ if (area >= FLT_EPSILON && uvarea >= FLT_EPSILON) {
+ /* Tag inversion by using the sign. */
+ return (area > uvarea) ? (uvarea / area) : -(area / uvarea);
+ }
+ return 0.0f;
+}
+
+BLI_INLINE float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_tot_ratio)
+{
+ ratio *= (ratio > 0.0f) ? tot_ratio : -inv_tot_ratio;
+ return (ratio > 1.0f) ? (1.0f / ratio) : ratio;
+}
+
+static void extract_edituv_stretch_area_finish(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *UNUSED(data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ float tot_area = 0.0f, tot_uv_area = 0.0f;
+ float *area_ratio = static_cast<float *>(MEM_mallocN(sizeof(float) * mr->poly_len, __func__));
+
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ CustomData *cd_ldata = &mr->bm->ldata;
+ int uv_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV);
+
+ BMFace *efa;
+ BMIter f_iter;
+ int f;
+ BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) {
+ float area = BM_face_calc_area(efa);
+ float uvarea = BM_face_calc_area_uv(efa, uv_ofs);
+ tot_area += area;
+ tot_uv_area += uvarea;
+ area_ratio[f] = area_ratio_get(area, uvarea);
+ }
+ }
+ else {
+ BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH));
+ const MLoopUV *uv_data = (const MLoopUV *)CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
+ const MPoly *mp = mr->mpoly;
+ for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ float area = BKE_mesh_calc_poly_area(mp, &mr->mloop[mp->loopstart], mr->mvert);
+ float uvarea = BKE_mesh_calc_poly_uv_area(mp, uv_data);
+ tot_area += area;
+ tot_uv_area += uvarea;
+ area_ratio[mp_index] = area_ratio_get(area, uvarea);
+ }
+ }
+
+ cache->tot_area = tot_area;
+ cache->tot_uv_area = tot_uv_area;
+
+ /* Convert in place to avoid an extra allocation */
+ uint16_t *poly_stretch = (uint16_t *)area_ratio;
+ for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) {
+ poly_stretch[mp_index] = area_ratio[mp_index] * SHRT_MAX;
+ }
+
+ /* Copy face data for each loop. */
+ uint16_t *loop_stretch = (uint16_t *)GPU_vertbuf_get_data(vbo);
+
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ BMFace *efa;
+ BMIter f_iter;
+ int f, l_index = 0;
+ BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) {
+ for (int i = 0; i < efa->len; i++, l_index++) {
+ loop_stretch[l_index] = poly_stretch[f];
+ }
+ }
+ }
+ else {
+ BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH));
+ const MPoly *mp = mr->mpoly;
+ for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ for (int i = 0; i < mp->totloop; i++, l_index++) {
+ loop_stretch[l_index] = poly_stretch[mp_index];
+ }
+ }
+ }
+
+ MEM_freeN(area_ratio);
+}
+
+constexpr MeshExtract create_extractor_edituv_stretch_area()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_edituv_stretch_area_init;
+ extractor.finish = extract_edituv_stretch_area_finish;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = 0;
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_area);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_edituv_stretch_area =
+ blender::draw::create_extractor_edituv_stretch_area();
+}