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
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup obj
*/
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BLI_delaunay_2d.h"
#include "BLI_math_vector.h"
#include "BLI_set.hh"
#include "DNA_object_types.h"
#include "IO_wavefront_obj.h"
#include "importer_mesh_utils.hh"
namespace blender::io::obj {
Vector<Vector<int>> fixup_invalid_polygon(Span<float3> vertex_coords,
Span<int> face_vertex_indices)
{
using namespace blender::meshintersect;
if (face_vertex_indices.size() < 3) {
return {};
}
/* Calculate face normal, to project verts to 2D. */
float normal[3] = {0, 0, 0};
float3 co_prev = vertex_coords[face_vertex_indices.last()];
for (int idx : face_vertex_indices) {
BLI_assert(idx >= 0 && idx < vertex_coords.size());
float3 co_curr = vertex_coords[idx];
add_newell_cross_v3_v3v3(normal, co_prev, co_curr);
co_prev = co_curr;
}
if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
normal[2] = 1.0f;
}
float axis_mat[3][3];
axis_dominant_v3_to_m3(axis_mat, normal);
/* Prepare data for CDT. */
CDT_input<double> input;
input.vert.reinitialize(face_vertex_indices.size());
input.face.reinitialize(1);
input.face[0].resize(face_vertex_indices.size());
for (int64_t i = 0; i < face_vertex_indices.size(); ++i) {
input.face[0][i] = i;
}
input.epsilon = 1.0e-6f;
input.need_ids = true;
/* Project vertices to 2D. */
for (size_t i = 0; i < face_vertex_indices.size(); ++i) {
int idx = face_vertex_indices[i];
BLI_assert(idx >= 0 && idx < vertex_coords.size());
float3 coord = vertex_coords[idx];
float2 coord2d;
mul_v2_m3v3(coord2d, axis_mat, coord);
input.vert[i] = double2(coord2d.x, coord2d.y);
}
CDT_result<double> res = delaunay_2d_calc(input, CDT_CONSTRAINTS_VALID_BMESH_WITH_HOLES);
/* Emit new face information from CDT result. */
Vector<Vector<int>> faces;
faces.reserve(res.face.size());
for (const auto &f : res.face) {
Vector<int> face_verts;
face_verts.reserve(f.size());
for (int64_t i = 0; i < f.size(); ++i) {
int idx = f[i];
BLI_assert(idx >= 0 && idx < res.vert_orig.size());
if (res.vert_orig[idx].is_empty()) {
/* If we have a whole new vertex in the tessellated result,
* we won't quite know what to do with it (how to create normal/UV
* for it, for example). Such vertices are often due to
* self-intersecting polygons. Just skip them from the output
* polygon. */
}
else {
/* Vertex corresponds to one or more of the input vertices, use it. */
idx = res.vert_orig[idx][0];
BLI_assert(idx >= 0 && idx < face_vertex_indices.size());
face_verts.append(idx);
}
}
faces.append(face_verts);
}
return faces;
}
void transform_object(Object *object, const OBJImportParams &import_params)
{
float axes_transform[3][3];
unit_m3(axes_transform);
float obmat[4][4];
unit_m4(obmat);
/* +Y-forward and +Z-up are the default Blender axis settings. */
mat3_from_axis_conversion(
IO_AXIS_Y, IO_AXIS_Z, import_params.forward_axis, import_params.up_axis, axes_transform);
copy_m4_m3(obmat, axes_transform);
BKE_object_apply_mat4(object, obmat, true, false);
if (import_params.clamp_size != 0.0f) {
float3 max_coord(-INT_MAX);
float3 min_coord(INT_MAX);
BoundBox *bb = BKE_mesh_boundbox_get(object);
for (const float(&vertex)[3] : bb->vec) {
for (int axis = 0; axis < 3; axis++) {
max_coord[axis] = max_ff(max_coord[axis], vertex[axis]);
min_coord[axis] = min_ff(min_coord[axis], vertex[axis]);
}
}
const float max_diff = max_fff(
max_coord[0] - min_coord[0], max_coord[1] - min_coord[1], max_coord[2] - min_coord[2]);
float scale = 1.0f;
while (import_params.clamp_size < max_diff * scale) {
scale = scale / 10;
}
copy_v3_fl(object->scale, scale);
}
}
} // namespace blender::io::obj
|