Blender  V2.93
quadriflow_capi.cpp
Go to the documentation of this file.
1 // Copyright 2019 Blender Foundation. All rights reserved.
2 //
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License
5 // as published by the Free Software Foundation; either version 2
6 // of the License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software Foundation,
15 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 //
17 // Author: Sebastian Parborg, Pablo Dobarro
18 
19 #include <unordered_map>
20 
21 #include "MEM_guardedalloc.h"
22 
23 #include "quadriflow_capi.hpp"
24 #include "config.hpp"
25 #include "field-math.hpp"
26 #include "optimizer.hpp"
27 #include "parametrizer.hpp"
28 #include "loader.hpp"
29 
30 using namespace qflow;
31 
32 struct ObjVertex {
33  uint32_t p = (uint32_t)-1;
34  uint32_t n = (uint32_t)-1;
35  uint32_t uv = (uint32_t)-1;
36 
38  {
39  }
40 
42  {
43  p = pi;
44  }
45 
46  bool operator==(const ObjVertex &v) const
47  {
48  return v.p == p && v.n == n && v.uv == uv;
49  }
50 };
51 
52 struct ObjVertexHash {
53  std::size_t operator()(const ObjVertex &v) const
54  {
55  size_t hash = std::hash<uint32_t>()(v.p);
56  hash = hash * 37 + std::hash<uint32_t>()(v.uv);
57  hash = hash * 37 + std::hash<uint32_t>()(v.n);
58  return hash;
59  }
60 };
61 
62 typedef std::unordered_map<ObjVertex, uint32_t, ObjVertexHash> VertexMap;
63 
64 static int check_if_canceled(float progress,
65  void (*update_cb)(void *, float progress, int *cancel),
66  void *update_cb_data)
67 {
68  int cancel = 0;
69  update_cb(update_cb_data, progress, &cancel);
70  return cancel;
71 }
72 
74  void (*update_cb)(void *, float progress, int *cancel),
75  void *update_cb_data)
76 {
77  Parametrizer field;
78  VertexMap vertexMap;
79 
80  /* Get remeshing parameters. */
81  int faces = qrd->target_faces;
82 
83  if (qrd->preserve_sharp) {
84  field.flag_preserve_sharp = 1;
85  }
86  if (qrd->preserve_boundary) {
87  field.flag_preserve_boundary = 1;
88  }
89  if (qrd->adaptive_scale) {
90  field.flag_adaptive_scale = 1;
91  }
92  if (qrd->minimum_cost_flow) {
93  field.flag_minimum_cost_flow = 1;
94  }
95  if (qrd->aggresive_sat) {
96  field.flag_aggresive_sat = 1;
97  }
98  if (qrd->rng_seed) {
99  field.hierarchy.rng_seed = qrd->rng_seed;
100  }
101 
102  if (check_if_canceled(0.0f, update_cb, update_cb_data) != 0) {
103  return;
104  }
105 
106  /* Copy mesh to quadriflow data structures. */
107  std::vector<Vector3d> positions;
108  std::vector<uint32_t> indices;
109  std::vector<ObjVertex> vertices;
110 
111  for (int i = 0; i < qrd->totverts; i++) {
112  Vector3d v(qrd->verts[i * 3], qrd->verts[i * 3 + 1], qrd->verts[i * 3 + 2]);
113  positions.push_back(v);
114  }
115 
116  for (int q = 0; q < qrd->totfaces; q++) {
117  Vector3i f(qrd->faces[q * 3], qrd->faces[q * 3 + 1], qrd->faces[q * 3 + 2]);
118 
119  ObjVertex tri[6];
120  int nVertices = 3;
121 
122  tri[0] = ObjVertex(f[0]);
123  tri[1] = ObjVertex(f[1]);
124  tri[2] = ObjVertex(f[2]);
125 
126  for (int i = 0; i < nVertices; ++i) {
127  const ObjVertex &v = tri[i];
128  VertexMap::const_iterator it = vertexMap.find(v);
129  if (it == vertexMap.end()) {
130  vertexMap[v] = (uint32_t)vertices.size();
131  indices.push_back((uint32_t)vertices.size());
132  vertices.push_back(v);
133  }
134  else {
135  indices.push_back(it->second);
136  }
137  }
138  }
139 
140  field.F.resize(3, indices.size() / 3);
141  memcpy(field.F.data(), indices.data(), sizeof(uint32_t) * indices.size());
142 
143  field.V.resize(3, vertices.size());
144  for (uint32_t i = 0; i < vertices.size(); ++i) {
145  field.V.col(i) = positions.at(vertices[i].p);
146  }
147 
148  if (check_if_canceled(0.1f, update_cb, update_cb_data)) {
149  return;
150  }
151 
152  /* Start processing the input mesh data */
153  field.NormalizeMesh();
154  field.Initialize(faces);
155 
156  if (check_if_canceled(0.2f, update_cb, update_cb_data)) {
157  return;
158  }
159 
160  /* Setup mesh boundary constraints if needed */
161  if (field.flag_preserve_boundary) {
162  Hierarchy &mRes = field.hierarchy;
163  mRes.clearConstraints();
164  for (uint32_t i = 0; i < 3 * mRes.mF.cols(); ++i) {
165  if (mRes.mE2E[i] == -1) {
166  uint32_t i0 = mRes.mF(i % 3, i / 3);
167  uint32_t i1 = mRes.mF((i + 1) % 3, i / 3);
168  Vector3d p0 = mRes.mV[0].col(i0), p1 = mRes.mV[0].col(i1);
169  Vector3d edge = p1 - p0;
170  if (edge.squaredNorm() > 0) {
171  edge.normalize();
172  mRes.mCO[0].col(i0) = p0;
173  mRes.mCO[0].col(i1) = p1;
174  mRes.mCQ[0].col(i0) = mRes.mCQ[0].col(i1) = edge;
175  mRes.mCQw[0][i0] = mRes.mCQw[0][i1] = mRes.mCOw[0][i0] = mRes.mCOw[0][i1] = 1.0;
176  }
177  }
178  }
179  mRes.propagateConstraints();
180  }
181 
182  /* Optimize the mesh field orientations (tangental field etc) */
183  Optimizer::optimize_orientations(field.hierarchy);
184  field.ComputeOrientationSingularities();
185 
186  if (check_if_canceled(0.3f, update_cb, update_cb_data)) {
187  return;
188  }
189 
190  if (field.flag_adaptive_scale == 1) {
191  field.EstimateSlope();
192  }
193 
194  if (check_if_canceled(0.4f, update_cb, update_cb_data)) {
195  return;
196  }
197 
198  Optimizer::optimize_scale(field.hierarchy, field.rho, field.flag_adaptive_scale);
199  field.flag_adaptive_scale = 1;
200 
201  Optimizer::optimize_positions(field.hierarchy, field.flag_adaptive_scale);
202 
203  field.ComputePositionSingularities();
204 
205  if (check_if_canceled(0.5f, update_cb, update_cb_data)) {
206  return;
207  }
208 
209  /* Compute the final quad geomtry using a maxflow solver */
210  field.ComputeIndexMap();
211 
212  if (check_if_canceled(0.9f, update_cb, update_cb_data)) {
213  return;
214  }
215 
216  /* Get the output mesh data */
217  qrd->out_totverts = field.O_compact.size();
218  qrd->out_totfaces = field.F_compact.size();
219 
220  qrd->out_verts = (float *)MEM_malloc_arrayN(
221  qrd->out_totverts, 3 * sizeof(float), "quadriflow remesher out verts");
222  qrd->out_faces = (unsigned int *)MEM_malloc_arrayN(
223  qrd->out_totfaces, 4 * sizeof(unsigned int), "quadriflow remesh out quads");
224 
225  for (int i = 0; i < qrd->out_totverts; i++) {
226  auto t = field.O_compact[i] * field.normalize_scale + field.normalize_offset;
227  qrd->out_verts[i * 3] = t[0];
228  qrd->out_verts[i * 3 + 1] = t[1];
229  qrd->out_verts[i * 3 + 2] = t[2];
230  }
231 
232  for (int i = 0; i < qrd->out_totfaces; i++) {
233  qrd->out_faces[i * 4] = field.F_compact[i][0];
234  qrd->out_faces[i * 4 + 1] = field.F_compact[i][1];
235  qrd->out_faces[i * 4 + 2] = field.F_compact[i][2];
236  qrd->out_faces[i * 4 + 3] = field.F_compact[i][3];
237  }
238 }
_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
static ushort indices[]
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
static char faces[256]
#define hash
Definition: noise.c:169
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:120
unsigned int uint32_t
Definition: stdint.h:83
std::size_t operator()(const ObjVertex &v) const
bool operator==(const ObjVertex &v) const
ObjVertex(uint32_t pi)
unsigned int * out_faces