Blender V4.3
importer_mesh_utils.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BKE_mesh.hh"
10#include "BKE_object.hh"
11
12#include "BLI_delaunay_2d.hh"
13#include "BLI_math_geom.h"
14#include "BLI_math_matrix.h"
15#include "BLI_math_rotation.h"
16#include "BLI_math_vector.h"
17
18#include "DNA_object_types.h"
19
20#include "IO_wavefront_obj.hh"
21
23
24#include <numeric>
25
26namespace blender::io::obj {
27
29{
30 using namespace blender::meshintersect;
31 if (face_verts.size() < 3) {
32 return {};
33 }
34
35 const float3 normal = bke::mesh::face_normal_calc(vert_positions, face_verts);
36 float axis_mat[3][3];
37 axis_dominant_v3_to_m3(axis_mat, normal);
38
39 /* Project vertices to 2D. */
40 Array<double2> input_verts(face_verts.size());
41 for (const int i : face_verts.index_range()) {
42 int idx = face_verts[i];
43 BLI_assert(idx >= 0 && idx < vert_positions.size());
44 float2 coord2d;
45 mul_v2_m3v3(coord2d, axis_mat, vert_positions[idx]);
46 input_verts[i] = double2(coord2d.x, coord2d.y);
47 }
48
49 Array<Vector<int>> input_faces(1);
50 input_faces.first().resize(input_verts.size());
51
52 std::iota(input_faces.first().begin(), input_faces.first().end(), 0);
53
54 /* Prepare data for CDT. */
56 input.vert = std::move(input_verts);
57 input.face = std::move(input_faces);
58 input.epsilon = 1.0e-6f;
59 input.need_ids = true;
61
62 /* Emit new face information from CDT result. */
64 faces.reserve(res.face.size());
65 for (const auto &res_face : res.face) {
66 Vector<int> res_face_verts;
67 res_face_verts.reserve(res_face.size());
68 for (int64_t i = 0; i < res_face.size(); ++i) {
69 int idx = res_face[i];
70 BLI_assert(idx >= 0 && idx < res.vert_orig.size());
71 if (res.vert_orig[idx].is_empty()) {
72 /* If we have a whole new vertex in the tessellated result, we won't quite know what to do
73 * with it (how to create normal/UV for it, for example). Such vertices are often due to
74 * self-intersecting faces. Just skip them from the output face. */
75 }
76 else {
77 /* Vertex corresponds to one or more of the input vertices, use it. */
78 idx = res.vert_orig[idx][0];
79 BLI_assert(idx >= 0 && idx < face_verts.size());
80 res_face_verts.append(idx);
81 }
82 }
83 faces.append(res_face_verts);
84 }
85 return faces;
86}
87
88void transform_object(Object *object, const OBJImportParams &import_params)
89{
90 float axes_transform[3][3];
91 unit_m3(axes_transform);
92 float obmat[4][4];
93 unit_m4(obmat);
94 /* +Y-forward and +Z-up are the default Blender axis settings. */
96 IO_AXIS_Y, IO_AXIS_Z, import_params.forward_axis, import_params.up_axis, axes_transform);
97 copy_m4_m3(obmat, axes_transform);
98
99 float scale_vec[3] = {
100 import_params.global_scale, import_params.global_scale, import_params.global_scale};
101 rescale_m4(obmat, scale_vec);
102 BKE_object_apply_mat4(object, obmat, true, false);
103
104 if (import_params.clamp_size != 0.0f) {
105 BLI_assert(object->type == OB_MESH);
106 const Mesh *mesh = static_cast<const Mesh *>(object->data);
107 const Bounds<float3> bounds = *mesh->bounds_min_max();
108 const float max_diff = math::reduce_max(bounds.max - bounds.min);
109
110 float scale = 1.0f;
111 while (import_params.clamp_size < max_diff * scale) {
112 scale = scale / 10;
113 }
114 copy_v3_fl(object->scale, scale);
115 }
116}
117
118std::string get_geometry_name(const std::string &full_name, char separator)
119{
120 if (separator == 0) {
121 return full_name;
122 }
123 size_t pos = full_name.find_last_of(separator);
124 if (pos == std::string::npos) {
125 return full_name;
126 }
127 return full_name.substr(pos + 1);
128}
129
130} // namespace blender::io::obj
General operations, lookup, etc. for blender objects.
void BKE_object_apply_mat4(Object *ob, const float mat[4][4], bool use_compat, bool use_parent)
#define BLI_assert(a)
Definition BLI_assert.h:50
@ CDT_CONSTRAINTS_VALID_BMESH_WITH_HOLES
void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
Normal to x,y matrix.
void unit_m3(float m[3][3])
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
void unit_m4(float m[4][4])
Definition rct.c:1127
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void rescale_m4(float mat[4][4], const float scale[3])
bool mat3_from_axis_conversion(int src_forward, int src_up, int dst_forward, int dst_up, float r_mat[3][3])
MINLINE void copy_v3_fl(float r[3], float f)
Object is a sort of wrapper for general info.
@ OB_MESH
@ IO_AXIS_Y
@ IO_AXIS_Z
int64_t size() const
Definition BLI_array.hh:245
const T & first() const
Definition BLI_array.hh:270
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
void append(const T &value)
void reserve(const int64_t min_capacity)
blender::meshintersect::CDT_result< double > delaunay_2d_calc(const CDT_input< double > &input, CDT_output_type output_type)
static char faces[256]
float3 face_normal_calc(Span< float3 > vert_positions, Span< int > face_verts)
void transform_object(Object *object, const OBJImportParams &import_params)
Vector< Vector< int > > fixup_invalid_face(Span< float3 > vert_positions, Span< int > face_verts)
std::string get_geometry_name(const std::string &full_name, char separator)
T reduce_max(const VecBase< T, Size > &a)
VecBase< double, 2 > double2
__int64 int64_t
Definition stdint.h:89