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

obj_export_mesh.hh « exporter « wavefront_obj « io « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ec98468e2debd55e29672af4aa69501781c72c6e (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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
/* SPDX-License-Identifier: GPL-2.0-or-later */

/** \file
 * \ingroup obj
 */

#pragma once

#include <optional>

#include "BLI_math_vec_types.hh"
#include "BLI_utility_mixins.hh"
#include "BLI_vector.hh"

#include "bmesh.h"
#include "bmesh_tools.h"

#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"

#include "IO_wavefront_obj.h"

namespace blender::io::obj {
/** Denote absence for usually non-negative numbers. */
const int NOT_FOUND = -1;
/** Any negative number other than `NOT_FOUND` to initialize usually non-negative numbers. */
const int NEGATIVE_INIT = -10;

/**
 * #std::unique_ptr than handles freeing #BMesh.
 */
struct CustomBMeshDeleter {
  void operator()(BMesh *bmesh)
  {
    if (bmesh) {
      BM_mesh_free(bmesh);
    }
  }
};

using unique_bmesh_ptr = std::unique_ptr<BMesh, CustomBMeshDeleter>;

class OBJMesh : NonCopyable {
 private:
  /**
   * We need to copy the entire Object structure here because the dependency graph iterator
   * sometimes builds an Object in a temporary space that doesn't persist.
   */
  Object export_object_eval_;
  Mesh *export_mesh_eval_;
  /**
   * For curves which are converted to mesh, and triangulated meshes, a new mesh is allocated.
   */
  bool mesh_eval_needs_free_ = false;
  /**
   * Final transform of an object obtained from export settings (up_axis, forward_axis) and the
   * object's world transform matrix.
   */
  float world_and_axes_transform_[4][4];
  float world_and_axes_normal_transform_[3][3];
  bool mirrored_transform_;

  /**
   * Total UV vertices in a mesh's texture map.
   */
  int tot_uv_vertices_ = 0;
  /**
   * Per-polygon-per-vertex UV vertex indices.
   */
  Vector<Vector<int>> uv_indices_;
  /*
   * UV vertices.
   */
  Vector<float2> uv_coords_;
  /**
   * Per-loop normal index.
   */
  Vector<int> loop_to_normal_index_;
  /*
   * Normal coords.
   */
  Vector<float3> normal_coords_;
  /*
   * Total number of normal indices (maximum entry, plus 1, in
   * the loop_to_norm_index_ vector).
   */
  int tot_normal_indices_ = 0;
  /**
   * Total smooth groups in an object.
   */
  int tot_smooth_groups_ = NEGATIVE_INIT;
  /**
   * Polygon aligned array of their smooth groups.
   */
  int *poly_smooth_groups_ = nullptr;
  /**
   * Order in which the polygons should be written into the file (sorted by material index).
   */
  Vector<int> poly_order_;

 public:
  /**
   * Store evaluated Object and Mesh pointers. Conditionally triangulate a mesh, or
   * create a new Mesh from a Curve.
   */
  OBJMesh(Depsgraph *depsgraph, const OBJExportParams &export_params, Object *mesh_object);
  ~OBJMesh();

  /* Clear various arrays to release potentially large memory allocations. */
  void clear();

  int tot_vertices() const;
  int tot_polygons() const;
  int tot_uv_vertices() const;
  int tot_normal_indices() const;
  int tot_edges() const;
  int tot_deform_groups() const;
  bool is_mirrored_transform() const
  {
    return mirrored_transform_;
  }

  /**
   * \return Total materials in the object.
   */
  int16_t tot_materials() const;
  /**
   * Return mat_nr-th material of the object. The given index should be zero-based.
   */
  const Material *get_object_material(int16_t mat_nr) const;

  void ensure_mesh_normals() const;
  void ensure_mesh_edges() const;

  /**
   * Calculate smooth groups of a smooth-shaded object.
   * \return A polygon aligned array of smooth group numbers.
   */
  void calc_smooth_groups(bool use_bitflags);
  /**
   * \return Smooth group of the polygon at the given index.
   */
  int ith_smooth_group(int poly_index) const;
  bool is_ith_poly_smooth(int poly_index) const;

  /**
   * Get object name as it appears in the outliner.
   */
  const char *get_object_name() const;
  /**
   * Get Object's Mesh's name.
   */
  const char *get_object_mesh_name() const;
  /**
   * Get object's material (at the given index) name. The given index should be zero-based.
   */
  const char *get_object_material_name(int16_t mat_nr) const;

  /**
   * Calculate coordinates of the vertex at the given index.
   */
  float3 calc_vertex_coords(int vert_index, float global_scale) const;
  /**
   * Calculate vertex indices of all vertices of the polygon at the given index.
   */
  Vector<int> calc_poly_vertex_indices(int poly_index) const;
  /**
   * Calculate UV vertex coordinates of an Object.
   * Stores the coordinates and UV vertex indices in the member variables.
   */
  void store_uv_coords_and_indices();
  /* Get UV coordinates computed by store_uv_coords_and_indices. */
  const Vector<float2> &get_uv_coords() const
  {
    return uv_coords_;
  }
  Span<int> calc_poly_uv_indices(int poly_index) const;
  /**
   * Calculate polygon normal of a polygon at given index.
   *
   * Should be used for flat-shaded polygons.
   */
  float3 calc_poly_normal(int poly_index) const;
  /**
   * Find the unique normals of the mesh and stores them in a member variable.
   * Also stores the indices into that vector with for each loop.
   */
  void store_normal_coords_and_indices();
  /* Get normals calculate by store_normal_coords_and_indices. */
  const Vector<float3> &get_normal_coords() const
  {
    return normal_coords_;
  }
  /**
   * Calculate a polygon's polygon/loop normal indices.
   * \param poly_index: Index of the polygon to calculate indices for.
   * \return Vector of normal indices, aligned with vertices of polygon.
   */
  Vector<int> calc_poly_normal_indices(int poly_index) const;
  /**
   * Find the most representative vertex group of a polygon.
   *
   * This adds up vertex group weights, and the group with the largest
   * weight sum across the polygon is the one returned.
   *
   * group_weights is temporary storage to avoid reallocations, it must
   * be the size of amount of vertex groups in the object.
   */
  int16_t get_poly_deform_group_index(int poly_index, MutableSpan<float> group_weights) const;
  /**
   * Find the name of the vertex deform group at the given index.
   * The index indices into the #Object.defbase.
   */
  const char *get_poly_deform_group_name(int16_t def_group_index) const;

  /**
   * Calculate vertex indices of an edge's corners if it is a loose edge.
   */
  std::optional<std::array<int, 2>> calc_loose_edge_vert_indices(int edge_index) const;

  /**
   * Calculate the order in which the polygons should be written into the file (sorted by material
   * index).
   */
  void calc_poly_order();

  /**
   * Remap polygon index according to polygon writing order.
   * When materials are not being written, the polygon order array
   * might be empty, in which case remap is a no-op.
   */
  int remap_poly_index(int i) const
  {
    return i < 0 || i >= poly_order_.size() ? i : poly_order_[i];
  }

  Mesh *get_mesh() const
  {
    return export_mesh_eval_;
  }

 private:
  /**
   * Free the mesh if _the exporter_ created it.
   */
  void free_mesh_if_needed();
  /**
   * Allocate a new Mesh with triangulated polygons.
   *
   * The returned mesh can be the same as the old one.
   * \return Owning pointer to the new Mesh, and whether a new Mesh was created.
   */
  std::pair<Mesh *, bool> triangulate_mesh_eval();
  /**
   * Set the final transform after applying axes settings and an Object's world transform.
   */
  void set_world_axes_transform(eIOAxis forward, eIOAxis up);
};
}  // namespace blender::io::obj