Blender V5.0
ply_import_mesh.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
8
9#include "BKE_attribute.hh"
10#include "BKE_lib_id.hh"
11#include "BKE_mesh.hh"
12
14
15#include "BLI_color.hh"
16#include "BLI_math_vector.h"
17#include "BLI_span.hh"
18
19#include "ply_import_mesh.hh"
20
21#include "CLG_log.h"
22static CLG_LogRef LOG = {"io.ply"};
23
24namespace blender::io::ply {
26{
28 data.vertices.size(), data.edges.size(), data.face_sizes.size(), data.face_vertices.size());
29
30 mesh->vert_positions_for_write().copy_from(data.vertices);
31
32 bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
33
34 if (!data.edges.is_empty()) {
35 MutableSpan<int2> edges = mesh->edges_for_write();
36 for (const int i : data.edges.index_range()) {
37 int32_t v1 = data.edges[i].first;
38 int32_t v2 = data.edges[i].second;
39 if (v1 >= mesh->verts_num) {
40 CLOG_WARN(&LOG, "Invalid PLY vertex index in edge %i/1: %d", i, v1);
41 v1 = 0;
42 }
43 if (v2 >= mesh->verts_num) {
44 CLOG_WARN(&LOG, "Invalid PLY vertex index in edge %i/2: %d", i, v2);
45 v2 = 0;
46 }
47 edges[i] = {v1, v2};
48 }
49 }
50
51 /* Add faces to the mesh. */
52 if (!data.face_sizes.is_empty()) {
53 MutableSpan<int> face_offsets = mesh->face_offsets_for_write();
54 MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
55
56 /* Fill in face data. */
57 uint32_t offset = 0;
58 for (const int i : data.face_sizes.index_range()) {
59 uint32_t size = data.face_sizes[i];
60 face_offsets[i] = offset;
61 for (int j = 0; j < size; j++) {
62 uint32_t v = data.face_vertices[offset + j];
63 if (v >= mesh->verts_num) {
64 CLOG_WARN(&LOG, "Invalid PLY vertex index in face %i loop %i: %u", i, j, v);
65 v = 0;
66 }
67 corner_verts[offset + j] = data.face_vertices[offset + j];
68 }
69 offset += size;
70 }
71 }
72
73 /* Vertex colors */
74 if (!data.vertex_colors.is_empty() && params.vertex_colors != ePLYVertexColorMode::None) {
75 /* Create a data layer for vertex colors and set them. */
78
79 if (params.vertex_colors == ePLYVertexColorMode::sRGB) {
80 for (const int i : data.vertex_colors.index_range()) {
81 srgb_to_linearrgb_v4(colors.span[i], data.vertex_colors[i]);
82 }
83 }
84 else {
85 for (const int i : data.vertex_colors.index_range()) {
86 copy_v4_v4(colors.span[i], data.vertex_colors[i]);
87 }
88 }
89 colors.finish();
92 }
93
94 /* Uvmap */
95 if (!data.uv_coordinates.is_empty()) {
98 for (const int i : data.face_vertices.index_range()) {
99 uv_map.span[i] = data.uv_coordinates[data.face_vertices[i]];
100 }
101 uv_map.finish();
102 }
103
104 /* If we have custom vertex normals, set them
105 * (NOTE: important to do this after initializing the loops). */
106 bool set_custom_normals_for_verts = false;
107 if (!data.vertex_normals.is_empty()) {
108 if (!data.face_sizes.is_empty()) {
109 /* For a non-point-cloud mesh, set custom normals. */
110 /* Deferred because this relies on valid mesh data. */
111 set_custom_normals_for_verts = true;
112 }
113 else if (params.import_attributes) {
114 /* If we have no faces, add vertex normals as custom attribute. */
115 attributes.add<float3>(
116 "normal",
119 }
120 }
121 else {
122 /* No vertex normals: set faces to sharp. */
123 bke::mesh_smooth_set(*mesh, false);
124 }
125
126 /* Custom attributes: add them after anything above. */
127 if (params.import_attributes && !data.vertex_custom_attr.is_empty()) {
128 for (const PlyCustomAttribute &attr : data.vertex_custom_attr) {
129 attributes.add<float>(attr.name,
132 }
133 }
134
135 /* It's important to validate the mesh before using it's geometry to calculate derived data. */
136 {
137 /* Calculate edges from the rest of the mesh (this could be merged with validate). */
138 bke::mesh_calc_edges(*mesh, true, false);
139
140 bool verbose_validate = false;
141#ifndef NDEBUG
142 verbose_validate = true;
143#endif
144 BKE_mesh_validate(mesh, verbose_validate, false);
145 }
146
147 if (set_custom_normals_for_verts) {
148 bke::mesh_set_custom_normals_from_verts(*mesh, data.vertex_normals);
149 }
150
151 /* Merge all vertices on the same location. */
152 if (params.merge_verts) {
153 std::optional<Mesh *> merged_mesh = blender::geometry::mesh_merge_by_distance_all(
154 *mesh, IndexMask(mesh->verts_num), 0.0001f);
155 if (merged_mesh) {
156 BKE_id_free(nullptr, &mesh->id);
157 mesh = *merged_mesh;
158 }
159 }
160
161 return mesh;
162}
163} // namespace blender::io::ply
void BKE_id_attributes_default_color_set(struct ID *id, std::optional< blender::StringRef > name)
void BKE_id_attributes_active_color_set(struct ID *id, std::optional< blender::StringRef > name)
Definition attribute.cc:985
void BKE_id_free(Main *bmain, void *idv)
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)
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
MINLINE void copy_v4_v4(float r[4], const float a[4])
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:189
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static VArray from_span(Span< T > values)
bool add(const StringRef attribute_id, const AttrDomain domain, const AttrType data_type, const AttributeInit &initializer)
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, AttrType data_type)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define LOG(level)
Definition log.h:97
void mesh_smooth_set(Mesh &mesh, bool use_smooth, bool keep_sharp_edges=false)
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges)
void mesh_set_custom_normals_from_verts(Mesh &mesh, MutableSpan< float3 > vert_normals)
std::optional< Mesh * > mesh_merge_by_distance_all(const Mesh &mesh, const IndexMask &selection, float merge_distance)
Mesh * convert_ply_to_mesh(PlyData &data, const PLYImportParams &params)
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
VecBase< float, 3 > float3
int verts_num
i
Definition text_draw.cc:230