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, materials, created_materials,
obj, import_params.
relative_paths);
99 this->create_vertex_groups(
obj);
104void MeshFromGeometry::fixup_invalid_faces()
123 int vertex_idx = mesh_geometry_.
face_corners_[corner_idx].vert_index;
124 if (used_verts.
contains(vertex_idx)) {
128 used_verts.
add(vertex_idx);
144 const FaceCorner &corner = mesh_geometry_.face_corners_[corner_idx];
145 face_verts.
append(corner.vert_index);
146 face_normals.
append(corner.vertex_normal_index);
147 face_uvs.
append(corner.uv_vert_index);
155 mesh_geometry_.face_elements_.remove_and_reorder(face_idx);
161 for (Span<int> face : new_faces) {
162 if (face.size() < 3) {
166 new_face.vertex_group_index = face_vertex_group;
167 new_face.material_index = face_material;
168 new_face.shaded_smooth = face_shaded_smooth;
169 new_face.start_index_ = mesh_geometry_.face_corners_.size();
170 new_face.corner_count_ = face.size();
171 for (
int idx : face) {
173 mesh_geometry_.face_corners_.append({face_verts[idx], face_uvs[idx], face_normals[idx]});
175 mesh_geometry_.face_elements_.append(new_face);
176 mesh_geometry_.total_corner_ += face.size();
181void MeshFromGeometry::create_vertices(
Mesh *mesh)
183 MutableSpan<float3> positions = mesh->vert_positions_for_write();
188 mesh_geometry_.global_to_local_vertices_.
clear();
189 mesh_geometry_.global_to_local_vertices_.reserve(mesh_geometry_.vertices_.size());
190 for (
int vi = mesh_geometry_.vertex_index_min_; vi <= mesh_geometry_.vertex_index_max_; ++vi) {
191 BLI_assert(vi >= 0 && vi < global_vertices_.vertices.size());
192 if (!mesh_geometry_.vertices_.contains(vi)) {
195 int local_vi = int(mesh_geometry_.global_to_local_vertices_.size());
196 BLI_assert(local_vi >= 0 && local_vi < mesh->verts_num);
197 copy_v3_v3(positions[local_vi], global_vertices_.vertices[vi]);
198 mesh_geometry_.global_to_local_vertices_.add_new(vi, local_vi);
202void MeshFromGeometry::create_faces(
Mesh *mesh,
bool use_vertex_groups)
204 MutableSpan<MDeformVert> dverts;
205 const int64_t total_verts = mesh_geometry_.get_vertex_count();
206 if (use_vertex_groups && total_verts && mesh_geometry_.has_vertex_groups_) {
207 dverts = mesh->deform_verts_for_write();
210 Span<float3> positions = mesh->vert_positions();
211 MutableSpan<int> face_offsets = mesh->face_offsets_for_write();
212 MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
213 bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
214 bke::SpanAttributeWriter<int> material_indices =
217 const bool set_face_sharpness = !has_normals();
218 bke::SpanAttributeWriter<bool> sharp_faces = attributes.lookup_or_add_for_write_span<
bool>(
221 int corner_index = 0;
223 for (
int face_idx = 0; face_idx < mesh->
faces_num; ++face_idx) {
224 const FaceElem &curr_face = mesh_geometry_.face_elements_[face_idx];
225 if (curr_face.corner_count_ < 3) {
227 CLOG_WARN(&
LOG,
"Face with less than 3 vertices found, skipping.");
231 face_offsets[face_idx] = corner_index;
232 if (set_face_sharpness) {
235 sharp_faces.span[face_idx] = !curr_face.shaded_smooth;
238 material_indices.span[face_idx] = curr_face.material_index;
241 material_indices.span[face_idx] = std::max(material_indices.span[face_idx], 0);
243 for (
int idx = 0; idx < curr_face.corner_count_; ++idx) {
244 const FaceCorner &curr_corner = mesh_geometry_.face_corners_[curr_face.start_index_ + idx];
245 corner_verts[corner_index] = mesh_geometry_.global_to_local_vertices_.lookup_default(
246 curr_corner.vert_index, 0);
250 const int group_index = curr_face.vertex_group_index;
252 if (group_index >= 0 ||
true) {
262 if (!set_face_sharpness) {
269 positions, corner_verts.
slice(face_offsets[face_idx], curr_face.corner_count_));
270 if (area < 1.0e-12f) {
271 sharp_faces.span[face_idx] =
true;
276 material_indices.finish();
277 sharp_faces.finish();
280void MeshFromGeometry::create_vertex_groups(
Object *obj)
283 if (mesh->deform_verts().is_empty()) {
286 for (
const std::string &name : mesh_geometry_.group_order_) {
291void MeshFromGeometry::create_edges(
Mesh *mesh)
293 MutableSpan<int2> edges = mesh->edges_for_write();
295 const int64_t tot_edges{mesh_geometry_.edges_.size()};
296 const int64_t total_verts{mesh_geometry_.get_vertex_count()};
298 for (
int i = 0;
i < tot_edges; ++
i) {
299 const int2 &src_edge = mesh_geometry_.edges_[
i];
300 int2 &dst_edge = edges[
i];
301 dst_edge[0] = mesh_geometry_.global_to_local_vertices_.lookup_default(src_edge[0], 0);
302 dst_edge[1] = mesh_geometry_.global_to_local_vertices_.lookup_default(src_edge[1], 0);
303 BLI_assert(dst_edge[0] < total_verts && dst_edge[1] < total_verts);
311void MeshFromGeometry::create_uv_verts(
Mesh *mesh)
313 if (global_vertices_.uv_vertices.size() <= 0) {
317 bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
318 bke::SpanAttributeWriter<float2> uv_map = attributes.lookup_or_add_for_write_only_span<
float2>(
321 int corner_index = 0;
322 bool added_uv =
false;
324 for (
const FaceElem &curr_face : mesh_geometry_.face_elements_) {
325 for (
int idx = 0; idx < curr_face.corner_count_; ++idx) {
326 const FaceCorner &curr_corner = mesh_geometry_.face_corners_[curr_face.start_index_ + idx];
327 if (curr_corner.uv_vert_index >= 0 &&
328 curr_corner.uv_vert_index < global_vertices_.uv_vertices.size())
330 uv_map.span[corner_index] = global_vertices_.uv_vertices[curr_corner.uv_vert_index];
334 uv_map.span[corner_index] = {0.0f, 0.0f};
350 attributes.remove(
"UVMap");
355 const std::string &name,
356 Map<std::string, std::unique_ptr<MTLMaterial>> &materials,
362 if (found_mat !=
nullptr) {
369 const MTLMaterial &mtl = *materials.lookup_or_add(name, std::make_unique<MTLMaterial>());
378 created_materials.
add_new(name, mat);
382void MeshFromGeometry::create_materials(
Main *bmain,
383 Map<std::string, std::unique_ptr<MTLMaterial>> &materials,
390 bmain, name, materials, created_materials, relative_paths);
391 if (mat ==
nullptr) {
401bool MeshFromGeometry::has_normals()
const
403 return !global_vertices_.vert_normals.is_empty() && mesh_geometry_.total_corner_ != 0;
406void MeshFromGeometry::create_normals(
Mesh *mesh)
408 if (!has_normals()) {
412 Array<float3> corner_normals(mesh_geometry_.total_corner_);
413 int corner_index = 0;
414 for (
const FaceElem &curr_face : mesh_geometry_.face_elements_) {
415 for (
int idx = 0; idx < curr_face.corner_count_; ++idx) {
416 const FaceCorner &curr_corner = mesh_geometry_.face_corners_[curr_face.start_index_ + idx];
417 int n_index = curr_corner.vertex_normal_index;
419 if (n_index >= 0 && n_index < global_vertices_.vert_normals.size()) {
420 normal = global_vertices_.vert_normals[n_index];
422 corner_normals[corner_index] = normal;
429void MeshFromGeometry::create_colors(
Mesh *mesh)
432 if (global_vertices_.vertex_colors.is_empty()) {
437 for (
int vi : mesh_geometry_.vertices_) {
438 if (!global_vertices_.has_vertex_color(vi)) {
451 for (
auto item : mesh_geometry_.global_to_local_vertices_.items()) {
452 const int vi = item.key;
453 const int local_vi = item.value;
454 BLI_assert(vi >= 0 && vi < global_vertices_.vertex_colors.size());
455 BLI_assert(local_vi >= 0 && local_vi < mesh->verts_num);
456 const float3 &c = global_vertices_.vertex_colors[vi];
457 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)
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)
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
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)
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
bool import_vertex_groups
char collection_separator
Vector< std::string > material_order_
Vector< FaceCorner > face_corners_
Vector< FaceElem > face_elements_