Blender  V3.3
quadriflow_capi.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2019 Blender Foundation. All rights reserved. */
3 
4 #include <unordered_map>
5 
6 #include "MEM_guardedalloc.h"
7 
8 #include "config.hpp"
9 #include "field-math.hpp"
10 #include "loader.hpp"
11 #include "optimizer.hpp"
12 #include "parametrizer.hpp"
13 #include "quadriflow_capi.hpp"
14 
15 using namespace qflow;
16 
17 struct ObjVertex {
18  uint32_t p = (uint32_t)-1;
19  uint32_t n = (uint32_t)-1;
20  uint32_t uv = (uint32_t)-1;
21 
23  {
24  }
25 
27  {
28  p = pi;
29  }
30 
31  bool operator==(const ObjVertex &v) const
32  {
33  return v.p == p && v.n == n && v.uv == uv;
34  }
35 };
36 
37 struct ObjVertexHash {
38  std::size_t operator()(const ObjVertex &v) const
39  {
40  size_t hash = std::hash<uint32_t>()(v.p);
41  hash = hash * 37 + std::hash<uint32_t>()(v.uv);
42  hash = hash * 37 + std::hash<uint32_t>()(v.n);
43  return hash;
44  }
45 };
46 
47 typedef std::unordered_map<ObjVertex, uint32_t, ObjVertexHash> VertexMap;
48 
49 static int check_if_canceled(float progress,
50  void (*update_cb)(void *, float progress, int *cancel),
51  void *update_cb_data)
52 {
53  int cancel = 0;
54  update_cb(update_cb_data, progress, &cancel);
55  return cancel;
56 }
57 
59  void (*update_cb)(void *, float progress, int *cancel),
60  void *update_cb_data)
61 {
62  Parametrizer field;
63  VertexMap vertexMap;
64 
65  /* Get remeshing parameters. */
66  int faces = qrd->target_faces;
67 
68  if (qrd->preserve_sharp) {
69  field.flag_preserve_sharp = 1;
70  }
71  if (qrd->preserve_boundary) {
72  field.flag_preserve_boundary = 1;
73  }
74  if (qrd->adaptive_scale) {
75  field.flag_adaptive_scale = 1;
76  }
77  if (qrd->minimum_cost_flow) {
78  field.flag_minimum_cost_flow = 1;
79  }
80  if (qrd->aggresive_sat) {
81  field.flag_aggresive_sat = 1;
82  }
83  if (qrd->rng_seed) {
84  field.hierarchy.rng_seed = qrd->rng_seed;
85  }
86 
87  if (check_if_canceled(0.0f, update_cb, update_cb_data) != 0) {
88  return;
89  }
90 
91  /* Copy mesh to quadriflow data structures. */
92  std::vector<Vector3d> positions;
93  std::vector<uint32_t> indices;
94  std::vector<ObjVertex> vertices;
95 
96  for (int i = 0; i < qrd->totverts; i++) {
97  Vector3d v(qrd->verts[i * 3], qrd->verts[i * 3 + 1], qrd->verts[i * 3 + 2]);
98  positions.push_back(v);
99  }
100 
101  for (int q = 0; q < qrd->totfaces; q++) {
102  Vector3i f(qrd->faces[q * 3], qrd->faces[q * 3 + 1], qrd->faces[q * 3 + 2]);
103 
104  ObjVertex tri[6];
105  int nVertices = 3;
106 
107  tri[0] = ObjVertex(f[0]);
108  tri[1] = ObjVertex(f[1]);
109  tri[2] = ObjVertex(f[2]);
110 
111  for (int i = 0; i < nVertices; ++i) {
112  const ObjVertex &v = tri[i];
113  VertexMap::const_iterator it = vertexMap.find(v);
114  if (it == vertexMap.end()) {
115  vertexMap[v] = (uint32_t)vertices.size();
116  indices.push_back((uint32_t)vertices.size());
117  vertices.push_back(v);
118  }
119  else {
120  indices.push_back(it->second);
121  }
122  }
123  }
124 
125  field.F.resize(3, indices.size() / 3);
126  memcpy(field.F.data(), indices.data(), sizeof(uint32_t) * indices.size());
127 
128  field.V.resize(3, vertices.size());
129  for (uint32_t i = 0; i < vertices.size(); ++i) {
130  field.V.col(i) = positions.at(vertices[i].p);
131  }
132 
133  if (check_if_canceled(0.1f, update_cb, update_cb_data)) {
134  return;
135  }
136 
137  /* Start processing the input mesh data */
138  field.NormalizeMesh();
139  field.Initialize(faces);
140 
141  if (check_if_canceled(0.2f, update_cb, update_cb_data)) {
142  return;
143  }
144 
145  /* Setup mesh boundary constraints if needed */
146  if (field.flag_preserve_boundary) {
147  Hierarchy &mRes = field.hierarchy;
148  mRes.clearConstraints();
149  for (uint32_t i = 0; i < 3 * mRes.mF.cols(); ++i) {
150  if (mRes.mE2E[i] == -1) {
151  uint32_t i0 = mRes.mF(i % 3, i / 3);
152  uint32_t i1 = mRes.mF((i + 1) % 3, i / 3);
153  Vector3d p0 = mRes.mV[0].col(i0), p1 = mRes.mV[0].col(i1);
154  Vector3d edge = p1 - p0;
155  if (edge.squaredNorm() > 0) {
156  edge.normalize();
157  mRes.mCO[0].col(i0) = p0;
158  mRes.mCO[0].col(i1) = p1;
159  mRes.mCQ[0].col(i0) = mRes.mCQ[0].col(i1) = edge;
160  mRes.mCQw[0][i0] = mRes.mCQw[0][i1] = mRes.mCOw[0][i0] = mRes.mCOw[0][i1] = 1.0;
161  }
162  }
163  }
164  mRes.propagateConstraints();
165  }
166 
167  /* Optimize the mesh field orientations (tangental field etc) */
168  Optimizer::optimize_orientations(field.hierarchy);
169  field.ComputeOrientationSingularities();
170 
171  if (check_if_canceled(0.3f, update_cb, update_cb_data)) {
172  return;
173  }
174 
175  if (field.flag_adaptive_scale == 1) {
176  field.EstimateSlope();
177  }
178 
179  if (check_if_canceled(0.4f, update_cb, update_cb_data)) {
180  return;
181  }
182 
183  Optimizer::optimize_scale(field.hierarchy, field.rho, field.flag_adaptive_scale);
184  field.flag_adaptive_scale = 1;
185 
186  Optimizer::optimize_positions(field.hierarchy, field.flag_adaptive_scale);
187 
188  field.ComputePositionSingularities();
189 
190  if (check_if_canceled(0.5f, update_cb, update_cb_data)) {
191  return;
192  }
193 
194  /* Compute the final quad geomtry using a maxflow solver */
195  field.ComputeIndexMap();
196 
197  if (check_if_canceled(0.9f, update_cb, update_cb_data)) {
198  return;
199  }
200 
201  /* Get the output mesh data */
202  qrd->out_totverts = field.O_compact.size();
203  qrd->out_totfaces = field.F_compact.size();
204 
205  qrd->out_verts = (float *)MEM_malloc_arrayN(qrd->out_totverts, sizeof(float[3]), __func__);
206  qrd->out_faces = (int *)MEM_malloc_arrayN(qrd->out_totfaces, sizeof(int[4]), __func__);
207 
208  for (int i = 0; i < qrd->out_totverts; i++) {
209  auto t = field.O_compact[i] * field.normalize_scale + field.normalize_offset;
210  qrd->out_verts[i * 3] = t[0];
211  qrd->out_verts[i * 3 + 1] = t[1];
212  qrd->out_verts[i * 3 + 2] = t[2];
213  }
214 
215  for (int i = 0; i < qrd->out_totfaces; i++) {
216  qrd->out_faces[i * 4] = field.F_compact[i][0];
217  qrd->out_faces[i * 4 + 1] = field.F_compact[i][1];
218  qrd->out_faces[i * 4 + 2] = field.F_compact[i][2];
219  qrd->out_faces[i * 4 + 3] = field.F_compact[i][3];
220  }
221 }
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint i1
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v
ccl_gpu_kernel_postfix int ccl_global int * indices
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
static char faces[256]
MutableSpan< float3 > positions
#define hash
Definition: noise.c:153
void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd, void(*update_cb)(void *, float progress, int *cancel), void *update_cb_data)
static int check_if_canceled(float progress, void(*update_cb)(void *, float progress, int *cancel), void *update_cb_data)
std::unordered_map< ObjVertex, uint32_t, ObjVertexHash > VertexMap
static void update_cb(PBVHNode *node, void *rebuild)
Definition: sculpt_undo.c:133
unsigned int uint32_t
Definition: stdint.h:80
std::size_t operator()(const ObjVertex &v) const
bool operator==(const ObjVertex &v) const
ObjVertex(uint32_t pi)