39 const int64_t tot_verts_object{mesh_geometry_.get_vertex_count()};
40 if (tot_verts_object <= 0) {
45 this->fixup_invalid_faces();
49 mesh_geometry_.edges_.size(),
50 mesh_geometry_.face_elements_.size(),
51 mesh_geometry_.total_corner_);
53 this->create_vertices(mesh);
55 this->create_edges(mesh);
56 this->create_uv_verts(mesh);
57 this->create_normals(mesh);
58 this->create_colors(mesh);
60 if (import_params.
validate_meshes || mesh_geometry_.has_invalid_faces_) {
61 bool verbose_validate =
false;
63 verbose_validate =
true;
73 Map<std::string, std::unique_ptr<MTLMaterial>> &materials,
79 if (mesh ==
nullptr) {
85 if (ob_name.empty()) {
92 this->create_materials(bmain,
104 this->create_vertex_groups(
obj);
109void MeshFromGeometry::fixup_invalid_faces()
128 int vertex_idx = mesh_geometry_.
face_corners_[corner_idx].vert_index;
129 if (used_verts.
contains(vertex_idx)) {
133 used_verts.
add(vertex_idx);
141 Vector<int, 8> face_verts;
142 Vector<int, 8> face_uvs;
143 Vector<int, 8> face_normals;
149 const FaceCorner &corner = mesh_geometry_.face_corners_[corner_idx];
150 face_verts.
append(corner.vert_index);
151 face_normals.
append(corner.vertex_normal_index);
152 face_uvs.
append(corner.uv_vert_index);
160 mesh_geometry_.face_elements_.remove_and_reorder(face_idx);
163 Vector<Vector<int>> new_faces =
fixup_invalid_face(global_vertices_.vertices, face_verts);
166 for (Span<int> face : new_faces) {
167 if (face.size() < 3) {
171 new_face.vertex_group_index = face_vertex_group;
172 new_face.material_index = face_material;
173 new_face.shaded_smooth = face_shaded_smooth;
174 new_face.start_index_ = mesh_geometry_.face_corners_.size();
175 new_face.corner_count_ = face.size();
176 for (
int idx : face) {
178 mesh_geometry_.face_corners_.append({face_verts[idx], face_uvs[idx], face_normals[idx]});
180 mesh_geometry_.face_elements_.append(new_face);
181 mesh_geometry_.total_corner_ += face.size();
186void MeshFromGeometry::create_vertices(
Mesh *mesh)
188 MutableSpan<float3> positions = mesh->vert_positions_for_write();
193 mesh_geometry_.global_to_local_vertices_.
clear();
194 mesh_geometry_.global_to_local_vertices_.reserve(mesh_geometry_.vertices_.size());
195 for (
int vi = mesh_geometry_.vertex_index_min_; vi <= mesh_geometry_.vertex_index_max_; ++vi) {
196 BLI_assert(vi >= 0 && vi < global_vertices_.vertices.size());
197 if (!mesh_geometry_.vertices_.contains(vi)) {
200 int local_vi = int(mesh_geometry_.global_to_local_vertices_.size());
201 BLI_assert(local_vi >= 0 && local_vi < mesh->verts_num);
202 copy_v3_v3(positions[local_vi], global_vertices_.vertices[vi]);
203 mesh_geometry_.global_to_local_vertices_.add_new(vi, local_vi);
207void MeshFromGeometry::create_faces(
Mesh *mesh,
bool use_vertex_groups)
209 MutableSpan<MDeformVert> dverts;
210 const int64_t total_verts = mesh_geometry_.get_vertex_count();
211 if (use_vertex_groups && total_verts && mesh_geometry_.has_vertex_groups_) {
212 dverts = mesh->deform_verts_for_write();
215 Span<float3> positions = mesh->vert_positions();
216 MutableSpan<int> face_offsets = mesh->face_offsets_for_write();
217 MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
218 bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
219 bke::SpanAttributeWriter<int> material_indices =
222 const bool set_face_sharpness = !has_normals();
223 bke::SpanAttributeWriter<bool> sharp_faces = attributes.lookup_or_add_for_write_span<
bool>(
226 int corner_index = 0;
228 for (
int face_idx = 0; face_idx < mesh->
faces_num; ++face_idx) {
229 const FaceElem &curr_face = mesh_geometry_.face_elements_[face_idx];
230 if (curr_face.corner_count_ < 3) {
232 CLOG_WARN(&
LOG,
"Face with less than 3 vertices found, skipping.");
236 face_offsets[face_idx] = corner_index;
237 if (set_face_sharpness) {
240 sharp_faces.span[face_idx] = !curr_face.shaded_smooth;
243 material_indices.span[face_idx] = curr_face.material_index;
246 material_indices.span[face_idx] = std::max(material_indices.span[face_idx], 0);
248 for (
int idx = 0; idx < curr_face.corner_count_; ++idx) {
249 const FaceCorner &curr_corner = mesh_geometry_.face_corners_[curr_face.start_index_ + idx];
250 corner_verts[corner_index] = mesh_geometry_.global_to_local_vertices_.lookup_default(
251 curr_corner.vert_index, 0);
255 const int group_index = curr_face.vertex_group_index;
257 if (group_index >= 0 ||
true) {
267 if (!set_face_sharpness) {
274 positions, corner_verts.
slice(face_offsets[face_idx], curr_face.corner_count_));
275 if (area < 1.0e-12f) {
276 sharp_faces.span[face_idx] =
true;
281 material_indices.finish();
282 sharp_faces.finish();
285void MeshFromGeometry::create_vertex_groups(
Object *obj)
288 if (mesh->deform_verts().is_empty()) {
291 for (
const std::string &
name : mesh_geometry_.group_order_) {
296void MeshFromGeometry::create_edges(
Mesh *mesh)
298 MutableSpan<int2> edges = mesh->edges_for_write();
300 const int64_t tot_edges{mesh_geometry_.edges_.size()};
301 const int64_t total_verts{mesh_geometry_.get_vertex_count()};
303 for (
int i = 0;
i < tot_edges; ++
i) {
304 const int2 &src_edge = mesh_geometry_.edges_[
i];
305 int2 &dst_edge = edges[
i];
306 dst_edge[0] = mesh_geometry_.global_to_local_vertices_.lookup_default(src_edge[0], 0);
307 dst_edge[1] = mesh_geometry_.global_to_local_vertices_.lookup_default(src_edge[1], 0);
308 BLI_assert(dst_edge[0] < total_verts && dst_edge[1] < total_verts);
316void MeshFromGeometry::create_uv_verts(
Mesh *mesh)
318 if (global_vertices_.uv_vertices.size() <= 0) {
322 bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
323 bke::SpanAttributeWriter<float2> uv_map = attributes.lookup_or_add_for_write_only_span<
float2>(
326 int corner_index = 0;
327 bool added_uv =
false;
329 for (
const FaceElem &curr_face : mesh_geometry_.face_elements_) {
330 for (
int idx = 0; idx < curr_face.corner_count_; ++idx) {
331 const FaceCorner &curr_corner = mesh_geometry_.face_corners_[curr_face.start_index_ + idx];
332 if (curr_corner.uv_vert_index >= 0 &&
333 curr_corner.uv_vert_index < global_vertices_.uv_vertices.size())
335 uv_map.span[corner_index] = global_vertices_.uv_vertices[curr_corner.uv_vert_index];
339 uv_map.span[corner_index] = {0.0f, 0.0f};
355 attributes.remove(
"UVMap");
360 const std::string &
name,
361 Map<std::string, std::unique_ptr<MTLMaterial>> &materials,
368 if (found_mat !=
nullptr) {
374 if (existing_mat !=
nullptr &&
383 const MTLMaterial &mtl = *materials.lookup_or_add(
name, std::make_unique<MTLMaterial>());
397void MeshFromGeometry::create_materials(
Main *bmain,
398 Map<std::string, std::unique_ptr<MTLMaterial>> &materials,
406 bmain,
name, materials, created_materials, relative_paths, mtl_name_collision_mode);
407 if (mat ==
nullptr) {
417bool MeshFromGeometry::has_normals()
const
419 return !global_vertices_.vert_normals.is_empty() && mesh_geometry_.total_corner_ != 0;
422void MeshFromGeometry::create_normals(
Mesh *mesh)
424 if (!has_normals()) {
428 Array<float3> corner_normals(mesh_geometry_.total_corner_);
429 int corner_index = 0;
430 for (
const FaceElem &curr_face : mesh_geometry_.face_elements_) {
431 for (
int idx = 0; idx < curr_face.corner_count_; ++idx) {
432 const FaceCorner &curr_corner = mesh_geometry_.face_corners_[curr_face.start_index_ + idx];
433 int n_index = curr_corner.vertex_normal_index;
435 if (n_index >= 0 && n_index < global_vertices_.vert_normals.size()) {
436 normal = global_vertices_.vert_normals[n_index];
438 corner_normals[corner_index] = normal;
445void MeshFromGeometry::create_colors(
Mesh *mesh)
448 if (global_vertices_.vertex_colors.is_empty()) {
453 for (
int vi : mesh_geometry_.vertices_) {
454 if (!global_vertices_.has_vertex_color(vi)) {
467 for (
auto item : mesh_geometry_.global_to_local_vertices_.items()) {
468 const int vi = item.key;
469 const int local_vi = item.value;
470 BLI_assert(vi >= 0 && vi < global_vertices_.vertex_colors.size());
471 BLI_assert(local_vi >= 0 && local_vi < mesh->verts_num);
472 const float3 &c = global_vertices_.vertex_colors[vi];
473 colors[local_vi] =
float4(c.
x, c.
y, c.
z, 1.0);
void BKE_id_attributes_default_color_set(struct ID *id, std::optional< blender::StringRef > name)
struct CustomDataLayer * BKE_attribute_new(AttributeOwner &owner, blender::StringRef name, eCustomDataType type, blender::bke::AttrDomain domain, struct ReportList *reports)
void BKE_id_attributes_active_color_set(struct ID *id, std::optional< blender::StringRef > name)
ID * BKE_libblock_find_name(Main *bmain, short type, const char *name, const std::optional< Library * > lib=std::nullopt) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
General operations, lookup, etc. for materials.
void BKE_object_material_assign_single_obdata(Main *bmain, Object *ob, Material *ma, short act)
Material * BKE_material_add(Main *bmain, const char *name)
bool BKE_mesh_validate(Mesh *mesh, bool do_verbose, bool cddata_check_mask)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob, bool process_shape_keys=true)
void BKE_ntree_update_after_single_tree_change(Main &bmain, bNodeTree &modified_tree, const NodeTreeUpdateExtraParams ¶ms={})
General operations, lookup, etc. for blender objects.
void * BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name) ATTR_NONNULL(1)
Object * BKE_object_add_only_object(Main *bmain, int type, const char *name) ATTR_RETURNS_NONNULL
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define UNUSED_VARS_NDEBUG(...)
#define CLOG_WARN(clg_ref,...)
struct CustomDataLayer CustomDataLayer
struct MDeformWeight MDeformWeight
@ OBJ_MTL_NAME_COLLISION_REFERENCE_EXISTING
static AttributeOwner from_id(ID *id)
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr bool is_empty() const
void append(const T &value)
void reserve(const int64_t min_capacity)
const Value * lookup_ptr(const Key &key) const
void add_new(const Key &key, const Value &value)
bool contains(const Key &key) const
Mesh * create_mesh(const OBJImportParams &import_params)
Object * create_mesh_object(Main *bmain, Map< std::string, std::unique_ptr< MTLMaterial > > &materials, Map< std::string, Material * > &created_materials, const OBJImportParams &import_params)
float face_area_calc(Span< float3 > vert_positions, Span< int > face_verts)
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges)
void mesh_set_custom_normals(Mesh &mesh, MutableSpan< float3 > corner_normals)
static Material * get_or_create_material(Main *bmain, const std::string &name, Map< std::string, std::unique_ptr< MTLMaterial > > &materials, Map< std::string, Material * > &created_materials, bool relative_paths, eOBJMtlNameCollisionMode mtl_name_collision_mode)
bNodeTree * create_mtl_node_tree(Main *bmain, const MTLMaterial &mtl_mat, Material *mat, bool relative_paths)
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)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< float, 3 > float3
struct bNodeTree * nodetree
void clear(bool preserve_shaders=false) override
eOBJMtlNameCollisionMode mtl_name_collision_mode
bool import_vertex_groups
char collection_separator
Vector< std::string > material_order_
Vector< FaceCorner > face_corners_
Vector< FaceElem > face_elements_