7 #define DNA_DEPRECATED_ALLOW
36 export_object_eval_ = dna::shallow_copy(*obj_eval);
40 mesh_eval_needs_free_ =
false;
42 if (!export_mesh_eval_) {
48 mesh_eval_needs_free_ =
true;
51 std::tie(export_mesh_eval_, mesh_eval_needs_free_) = triangulate_mesh_eval();
64 void OBJMesh::free_mesh_if_needed()
66 if (mesh_eval_needs_free_ && export_mesh_eval_) {
68 export_mesh_eval_ =
nullptr;
69 mesh_eval_needs_free_ =
false;
75 free_mesh_if_needed();
76 uv_indices_.clear_and_make_inline();
77 uv_coords_.clear_and_make_inline();
79 normal_coords_.clear_and_make_inline();
81 if (poly_smooth_groups_) {
83 poly_smooth_groups_ =
nullptr;
87 std::pair<Mesh *, bool> OBJMesh::triangulate_mesh_eval()
89 if (export_mesh_eval_->
totpoly <= 0) {
90 return {export_mesh_eval_,
false};
95 bm_convert_params.calc_vert_normal =
true;
96 bm_convert_params.add_key_index =
false;
97 bm_convert_params.use_shapekey =
false;
101 const int triangulate_min_verts = 4;
108 triangulate_min_verts,
115 bmesh.get(),
nullptr, export_mesh_eval_);
116 free_mesh_if_needed();
117 return {triangulated,
true};
120 void OBJMesh::set_world_axes_transform(
const eIOAxis forward,
const eIOAxis up)
122 float axes_transform[3][3];
126 mul_m4_m3m4(world_and_axes_transform_, axes_transform, export_object_eval_.
obmat);
128 mul_v3_m3v3(world_and_axes_transform_[3], axes_transform, export_object_eval_.
obmat[3]);
129 world_and_axes_transform_[3][3] = export_object_eval_.
obmat[3][3];
132 float normal_matrix[3][3];
133 copy_m3_m4(normal_matrix, world_and_axes_transform_);
134 invert_m3_m3(world_and_axes_normal_transform_, normal_matrix);
141 return export_mesh_eval_->
totvert;
146 return export_mesh_eval_->
totpoly;
151 return tot_uv_vertices_;
156 return export_mesh_eval_->
totedge;
161 return export_mesh_eval_->
totcol;
166 return tot_normal_indices_;
174 return poly_smooth_groups_[poly_index];
192 export_mesh_eval_->
mpoly,
194 export_mesh_eval_->
mloop,
203 poly_order_.
resize(tot_polys);
204 for (
int i = 0; i < tot_polys; ++i) {
207 const MPoly *mpolys = export_mesh_eval_->
mpoly;
210 int mat_a = mpolys[a].mat_nr;
211 int mat_b = mpolys[b].mat_nr;
212 if (mat_a != mat_b) {
213 return mat_a < mat_b;
227 Object *obj =
const_cast<Object *
>(&export_object_eval_);
232 bool OBJMesh::is_ith_poly_smooth(
const int poly_index)
const
234 return export_mesh_eval_->mpoly[poly_index].
flag &
ME_SMOOTH;
237 int16_t OBJMesh::ith_poly_matnr(
const int poly_index)
const
239 BLI_assert(poly_index < export_mesh_eval_->totpoly);
240 const int16_t r_mat_nr = export_mesh_eval_->mpoly[poly_index].mat_nr;
241 return r_mat_nr >= 0 ? r_mat_nr :
NOT_FOUND;
244 const char *OBJMesh::get_object_name()
const
246 return export_object_eval_.id.name + 2;
249 const char *OBJMesh::get_object_mesh_name()
const
251 return export_mesh_eval_->id.name + 2;
254 const char *OBJMesh::get_object_material_name(
const int16_t mat_nr)
const
256 const Material *mat = get_object_material(mat_nr);
263 float3 OBJMesh::calc_vertex_coords(
const int vert_index,
const float scaling_factor)
const
266 copy_v3_v3(r_coords, export_mesh_eval_->mvert[vert_index].co);
267 mul_m4_v3(world_and_axes_transform_, r_coords);
272 Vector<int> OBJMesh::calc_poly_vertex_indices(
const int poly_index)
const
274 const MPoly &mpoly = export_mesh_eval_->mpoly[poly_index];
276 const int totloop = mpoly.
totloop;
278 for (
int loop_index = 0; loop_index < totloop; loop_index++) {
279 r_poly_vertex_indices[loop_index] = mloop[loop_index].
v;
281 return r_poly_vertex_indices;
284 void OBJMesh::store_uv_coords_and_indices()
286 const MPoly *mpoly = export_mesh_eval_->mpoly;
287 const MLoop *mloop = export_mesh_eval_->mloop;
288 const int totpoly = export_mesh_eval_->totpoly;
289 const int totvert = export_mesh_eval_->totvert;
293 tot_uv_vertices_ = 0;
299 mpoly, mloop, mloopuv, totpoly, totvert, limit,
false,
false);
301 uv_indices_.resize(totpoly);
304 uv_coords_.reserve(totvert);
306 tot_uv_vertices_ = 0;
307 for (
int vertex_index = 0; vertex_index < totvert; vertex_index++) {
309 for (; uv_vert; uv_vert = uv_vert->
next) {
311 tot_uv_vertices_ += 1;
316 uv_coords_.resize(tot_uv_vertices_);
319 uv_coords_[tot_uv_vertices_ - 1] =
float2(vert_uv_coords[0], vert_uv_coords[1]);
322 uv_indices_[uv_vert->
poly_index].resize(vertices_in_poly);
330 Span<int> OBJMesh::calc_poly_uv_indices(
const int poly_index)
const
332 if (uv_indices_.size() <= 0) {
335 BLI_assert(poly_index < export_mesh_eval_->totpoly);
337 return uv_indices_[poly_index];
340 float3 OBJMesh::calc_poly_normal(
const int poly_index)
const
343 const MPoly &poly = export_mesh_eval_->mpoly[poly_index];
345 const MVert &mvert = *(export_mesh_eval_->mvert);
347 mul_m3_v3(world_and_axes_normal_transform_, r_poly_normal);
349 return r_poly_normal;
355 float scale =
powf(10.0, round_digits);
356 return ceilf((scale * f - 0.49999999f)) / scale;
368 void OBJMesh::store_normal_coords_and_indices()
375 constexpr
int round_digits = 4;
376 int cur_normal_index = 0;
379 normal_to_index.
reserve(export_mesh_eval_->totpoly);
380 loop_to_normal_index_.resize(export_mesh_eval_->totloop);
381 loop_to_normal_index_.fill(-1);
382 const float(*lnors)[3] =
static_cast<const float(*)[3]
>(
384 for (
int poly_index = 0; poly_index < export_mesh_eval_->totpoly; ++poly_index) {
385 const MPoly &mpoly = export_mesh_eval_->mpoly[poly_index];
386 bool need_per_loop_normals = lnors !=
nullptr || (mpoly.
flag &
ME_SMOOTH);
387 if (need_per_loop_normals) {
388 for (
int loop_of_poly = 0; loop_of_poly < mpoly.
totloop; ++loop_of_poly) {
390 int loop_index = mpoly.
loopstart + loop_of_poly;
391 BLI_assert(loop_index < export_mesh_eval_->totloop);
393 mul_m3_v3(world_and_axes_normal_transform_, loop_normal);
396 int loop_norm_index = normal_to_index.
lookup_default(rounded_loop_normal, -1);
397 if (loop_norm_index == -1) {
398 loop_norm_index = cur_normal_index++;
399 normal_to_index.
add(rounded_loop_normal, loop_norm_index);
400 normal_coords_.append(rounded_loop_normal);
402 loop_to_normal_index_[loop_index] = loop_norm_index;
406 float3 poly_normal = calc_poly_normal(poly_index);
408 int poly_norm_index = normal_to_index.
lookup_default(rounded_poly_normal, -1);
409 if (poly_norm_index == -1) {
410 poly_norm_index = cur_normal_index++;
411 normal_to_index.
add(rounded_poly_normal, poly_norm_index);
412 normal_coords_.append(rounded_poly_normal);
414 for (
int i = 0; i < mpoly.
totloop; ++i) {
416 BLI_assert(loop_index < export_mesh_eval_->totloop);
417 loop_to_normal_index_[loop_index] = poly_norm_index;
421 tot_normal_indices_ = cur_normal_index;
424 Vector<int> OBJMesh::calc_poly_normal_indices(
const int poly_index)
const
426 if (loop_to_normal_index_.is_empty()) {
429 const MPoly &mpoly = export_mesh_eval_->mpoly[poly_index];
430 const int totloop = mpoly.
totloop;
432 for (
int poly_loop_index = 0; poly_loop_index < totloop; poly_loop_index++) {
433 int loop_index = mpoly.
loopstart + poly_loop_index;
434 r_poly_normal_indices[poly_loop_index] = loop_to_normal_index_[loop_index];
436 return r_poly_normal_indices;
439 int OBJMesh::tot_deform_groups()
const
447 int16_t OBJMesh::get_poly_deform_group_index(
const int poly_index,
450 BLI_assert(poly_index < export_mesh_eval_->totpoly);
459 group_weights.
fill(0);
460 bool found_any_group =
false;
461 const MPoly &mpoly = export_mesh_eval_->mpoly[poly_index];
463 for (
int loop_i = 0; loop_i < mpoly.
totloop; ++loop_i, ++mloop) {
465 for (
int weight_i = 0; weight_i < dvert.
totweight; ++weight_i) {
466 const auto group = dvert.
dw[weight_i].
def_nr;
467 if (group < group_weights.
size()) {
468 group_weights[group] += dvert.
dw[weight_i].
weight;
469 found_any_group =
true;
474 if (!found_any_group) {
478 int16_t max_idx = std::max_element(group_weights.
begin(), group_weights.
end()) -
479 group_weights.
begin();
483 const char *OBJMesh::get_poly_deform_group_name(
const int16_t def_group_index)
const
487 return vertex_group.
name;
490 std::optional<std::array<int, 2>> OBJMesh::calc_loose_edge_vert_indices(
const int edge_index)
const
492 const MEdge &
edge = export_mesh_eval_->medge[edge_index];
494 return std::array<int, 2>{
static_cast<int>(
edge.v1),
static_cast<int>(
edge.v2)};
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
void * CustomData_get_layer(const struct CustomData *data, int type)
void BKE_id_free(struct Main *bmain, void *idv)
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get_eval(struct Object *ob, short act)
void BKE_mesh_calc_edges_loose(struct Mesh *mesh)
struct BMesh * BKE_mesh_to_bmesh_ex(const struct Mesh *me, const struct BMeshCreateParams *create_params, const struct BMeshFromMeshParams *convert_params)
struct Mesh * BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm, const struct CustomData_MeshMasks *cd_mask_extra, const struct Mesh *me_settings)
void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly, const struct MLoop *loopstart, const struct MVert *mvarray, float r_no[3])
void BKE_mesh_calc_normals_split(struct Mesh *mesh)
struct Mesh * BKE_mesh_new_from_object(struct Depsgraph *depsgraph, struct Object *object, bool preserve_all_data_layers, bool preserve_origindex)
void BKE_mesh_calc_edges(struct Mesh *mesh, bool keep_existing_edges, bool select_new_edges)
UvMapVert * BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v)
int * BKE_mesh_calc_smoothgroups(const struct MEdge *medge, int totedge, const struct MPoly *mpoly, int totpoly, const struct MLoop *mloop, int totloop, int *r_totgroup, bool use_bitflags)
UvVertMap * BKE_mesh_uv_vert_map_create(const struct MPoly *mpoly, const struct MLoop *mloop, const struct MLoopUV *mloopuv, unsigned int totpoly, unsigned int totvert, const float limit[2], bool selected, bool use_winding)
void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
#define STD_UV_CONNECT_LIMIT
General operations, lookup, etc. for blender objects.
struct Mesh * BKE_object_get_pre_modified_mesh(const struct Object *object)
struct Mesh * BKE_object_get_evaluated_mesh(const struct Object *object)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void mul_m3_v3(const float M[3][3], float r[3])
void unit_m3(float m[3][3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
void mul_m4_v3(const float M[4][4], float r[3])
bool invert_m3_m3(float R[3][3], const float A[3][3])
float determinant_m3_array(const float m[3][3])
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
void transpose_m3(float R[3][3])
void mul_m4_m3m4(float R[4][4], const float A[3][3], const float B[4][4])
bool mat3_from_axis_conversion(int src_forward, int src_up, int dst_forward, int dst_up, float r_mat[3][3])
MINLINE float normalize_v3(float r[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
struct Depsgraph Depsgraph
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ MOD_TRIANGULATE_NGON_BEAUTY
@ MOD_TRIANGULATE_QUAD_SHORTEDGE
Object is a sort of wrapper for general info.
ATTR_WARN_UNUSED_RESULT const BMVert * v
void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method, const int min_vertices, const bool tag_only, BMOperator *op, BMOpSlot *slot_facemap_out, BMOpSlot *slot_facemap_double_out)
bool add(const Key &key, const Value &value)
Value lookup_default(const Key &key, const Value &default_value) const
constexpr int64_t size() const
constexpr T * end() const
constexpr void fill(const T &value)
constexpr T * begin() const
void resize(const int64_t new_size)
void clear_and_make_inline()
int tot_normal_indices() const
int ith_smooth_group(int poly_index) const
int16_t tot_materials() const
void calc_smooth_groups(bool use_bitflags)
int tot_uv_vertices() const
void ensure_mesh_normals() const
void ensure_mesh_edges() const
OBJMesh(Depsgraph *depsgraph, const OBJExportParams &export_params, Object *mesh_object)
const Depsgraph * depsgraph
void(* MEM_freeN)(void *vmemh)
static float round_float_to_n_digits(const float f, int round_digits)
std::unique_ptr< BMesh, CustomBMeshDeleter > unique_bmesh_ptr
static float3 round_float3_to_n_digits(const float3 &v, int round_digits)
void parallel_sort(RandomAccessIterator begin, RandomAccessIterator end)
vec_base< float, 2 > float2
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
bool export_triangulated_mesh
unsigned short loop_of_poly_index