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

extract_mesh.cc « mesh_extractors « intern « draw « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ec7d3a933b4e8b0b9c02c872b05c8d1595f4e21b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* SPDX-License-Identifier: GPL-2.0-or-later
 * Copyright 2021 Blender Foundation. All rights reserved. */

/** \file
 * \ingroup draw
 *
 * \brief Extraction of Mesh data into VBO to feed to GPU.
 */

#include "MEM_guardedalloc.h"

#include "DNA_object_types.h"

#include "ED_uvedit.h"

#include "extract_mesh.hh"

#include "draw_cache_impl.h"

void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferList *mbuflist)
{
  /* NOTE: POINTER_OFFSET on windows platforms casts internally to `void *`, but on GCC/CLANG to
   * `MeshBufferList *`. What shows a different usage versus intent. */
  void **buffer_ptr = (void **)POINTER_OFFSET(mbuflist, extractor->mesh_buffer_offset);
  void *buffer = *buffer_ptr;
  BLI_assert(buffer);
  return buffer;
}

eMRIterType mesh_extract_iter_type(const MeshExtract *ext)
{
  eMRIterType type = (eMRIterType)0;
  SET_FLAG_FROM_TEST(type, (ext->iter_looptri_bm || ext->iter_looptri_mesh), MR_ITER_LOOPTRI);
  SET_FLAG_FROM_TEST(type, (ext->iter_poly_bm || ext->iter_poly_mesh), MR_ITER_POLY);
  SET_FLAG_FROM_TEST(type, (ext->iter_ledge_bm || ext->iter_ledge_mesh), MR_ITER_LEDGE);
  SET_FLAG_FROM_TEST(type, (ext->iter_lvert_bm || ext->iter_lvert_mesh), MR_ITER_LVERT);
  return type;
}

/* ---------------------------------------------------------------------- */
/** \name Override extractors
 * Extractors can be overridden. When overridden a specialized version is used. The next functions
 * would check for any needed overrides and usage of the specialized version.
 * \{ */

static const MeshExtract *mesh_extract_override_hq_normals(const MeshExtract *extractor)
{
  if (extractor == &extract_pos_nor) {
    return &extract_pos_nor_hq;
  }
  if (extractor == &extract_lnor) {
    return &extract_lnor_hq;
  }
  if (extractor == &extract_tan) {
    return &extract_tan_hq;
  }
  if (extractor == &extract_fdots_nor) {
    return &extract_fdots_nor_hq;
  }
  return extractor;
}

static const MeshExtract *mesh_extract_override_single_material(const MeshExtract *extractor)
{
  if (extractor == &extract_tris) {
    return &extract_tris_single_mat;
  }
  return extractor;
}

const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor,
                                             const bool do_hq_normals,
                                             const bool do_single_mat)
{
  if (do_hq_normals) {
    extractor = mesh_extract_override_hq_normals(extractor);
  }

  if (do_single_mat) {
    extractor = mesh_extract_override_single_material(extractor);
  }

  return extractor;
}

/** \} */

/* ---------------------------------------------------------------------- */
/** \name Extract Edit Flag Utils
 * \{ */

void mesh_render_data_face_flag(const MeshRenderData *mr,
                                const BMFace *efa,
                                const int cd_ofs,
                                EditLoopData *eattr)
{
  if (efa == mr->efa_act) {
    eattr->v_flag |= VFLAG_FACE_ACTIVE;
  }
  if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
    eattr->v_flag |= VFLAG_FACE_SELECTED;
  }

  if (efa == mr->efa_act_uv) {
    eattr->v_flag |= VFLAG_FACE_UV_ACTIVE;
  }
  if ((cd_ofs != -1) && uvedit_face_select_test_ex(mr->toolsettings, (BMFace *)efa, cd_ofs)) {
    eattr->v_flag |= VFLAG_FACE_UV_SELECT;
  }

#ifdef WITH_FREESTYLE
  if (mr->freestyle_face_ofs != -1) {
    const FreestyleFace *ffa = (const FreestyleFace *)BM_ELEM_CD_GET_VOID_P(
        efa, mr->freestyle_face_ofs);
    if (ffa->flag & FREESTYLE_FACE_MARK) {
      eattr->v_flag |= VFLAG_FACE_FREESTYLE;
    }
  }
#endif
}

void mesh_render_data_loop_flag(const MeshRenderData *mr,
                                BMLoop *l,
                                const int cd_ofs,
                                EditLoopData *eattr)
{
  if (cd_ofs == -1) {
    return;
  }
  MLoopUV *luv = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_ofs);
  if (luv != nullptr && (luv->flag & MLOOPUV_PINNED)) {
    eattr->v_flag |= VFLAG_VERT_UV_PINNED;
  }
  if (uvedit_uv_select_test_ex(mr->toolsettings, l, cd_ofs)) {
    eattr->v_flag |= VFLAG_VERT_UV_SELECT;
  }
}

void mesh_render_data_loop_edge_flag(const MeshRenderData *mr,
                                     BMLoop *l,
                                     const int cd_ofs,
                                     EditLoopData *eattr)
{
  if (cd_ofs == -1) {
    return;
  }
  if (uvedit_edge_select_test_ex(mr->toolsettings, l, cd_ofs)) {
    eattr->v_flag |= VFLAG_EDGE_UV_SELECT;
    eattr->v_flag |= VFLAG_VERT_UV_SELECT;
  }
}

/** \} */