Blender V4.3
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
9#include "BKE_attribute.hh"
10#include "BKE_lib_id.hh"
11#include "BKE_mesh.hh"
12#include "BKE_mesh_runtime.hh"
13
15
16#include "BLI_color.hh"
17#include "BLI_math_vector.h"
18#include "BLI_span.hh"
19
20#include "ply_import_mesh.hh"
21
22namespace blender::io::ply {
24{
26 data.vertices.size(), data.edges.size(), data.face_sizes.size(), data.face_vertices.size());
27
28 mesh->vert_positions_for_write().copy_from(data.vertices);
29
30 bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
31
32 if (!data.edges.is_empty()) {
33 MutableSpan<int2> edges = mesh->edges_for_write();
34 for (const int i : data.edges.index_range()) {
35 int32_t v1 = data.edges[i].first;
36 int32_t v2 = data.edges[i].second;
37 if (v1 >= mesh->verts_num) {
38 fprintf(stderr, "Invalid PLY vertex index in edge %i/1: %d\n", i, v1);
39 v1 = 0;
40 }
41 if (v2 >= mesh->verts_num) {
42 fprintf(stderr, "Invalid PLY vertex index in edge %i/2: %d\n", i, v2);
43 v2 = 0;
44 }
45 edges[i] = {v1, v2};
46 }
47 }
48
49 /* Add faces to the mesh. */
50 if (!data.face_sizes.is_empty()) {
51 MutableSpan<int> face_offsets = mesh->face_offsets_for_write();
52 MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
53
54 /* Fill in face data. */
55 uint32_t offset = 0;
56 for (const int i : data.face_sizes.index_range()) {
57 uint32_t size = data.face_sizes[i];
58 face_offsets[i] = offset;
59 for (int j = 0; j < size; j++) {
60 uint32_t v = data.face_vertices[offset + j];
61 if (v >= mesh->verts_num) {
62 fprintf(stderr, "Invalid PLY vertex index in face %i loop %i: %u\n", i, j, v);
63 v = 0;
64 }
65 corner_verts[offset + j] = data.face_vertices[offset + j];
66 }
67 offset += size;
68 }
69 }
70
71 /* Vertex colors */
72 if (!data.vertex_colors.is_empty() && params.vertex_colors != PLY_VERTEX_COLOR_NONE) {
73 /* Create a data layer for vertex colors and set them. */
74 bke::SpanAttributeWriter colors = attributes.lookup_or_add_for_write_span<ColorGeometry4f>(
76
77 if (params.vertex_colors == PLY_VERTEX_COLOR_SRGB) {
78 for (const int i : data.vertex_colors.index_range()) {
79 srgb_to_linearrgb_v4(colors.span[i], data.vertex_colors[i]);
80 }
81 }
82 else {
83 for (const int i : data.vertex_colors.index_range()) {
84 copy_v4_v4(colors.span[i], data.vertex_colors[i]);
85 }
86 }
87 colors.finish();
88 BKE_id_attributes_active_color_set(&mesh->id, "Col");
90 }
91
92 /* Uvmap */
93 if (!data.uv_coordinates.is_empty()) {
94 bke::SpanAttributeWriter<float2> uv_map = attributes.lookup_or_add_for_write_only_span<float2>(
96 for (const int i : data.face_vertices.index_range()) {
97 uv_map.span[i] = data.uv_coordinates[data.face_vertices[i]];
98 }
99 uv_map.finish();
100 }
101
102 /* If we have custom vertex normals, set them
103 * (NOTE: important to do this after initializing the loops). */
104 bool set_custom_normals_for_verts = false;
105 if (!data.vertex_normals.is_empty()) {
106 if (!data.face_sizes.is_empty()) {
107 /* For a non-point-cloud mesh, set custom normals. */
108 /* Deferred because this relies on valid mesh data. */
109 set_custom_normals_for_verts = true;
110 }
111 else if (params.import_attributes) {
112 /* If we have no faces, add vertex normals as custom attribute. */
113 attributes.add<float3>(
114 "normal",
117 }
118 }
119 else {
120 /* No vertex normals: set faces to sharp. */
121 bke::mesh_smooth_set(*mesh, false);
122 }
123
124 /* Custom attributes: add them after anything above. */
125 if (params.import_attributes && !data.vertex_custom_attr.is_empty()) {
126 for (const PlyCustomAttribute &attr : data.vertex_custom_attr) {
127 attributes.add<float>(attr.name,
130 }
131 }
132
133 /* It's important to validate the mesh before using it's geometry to calculate derived data. */
134 {
135 /* Calculate edges from the rest of the mesh (this could be merged with validate). */
136 bke::mesh_calc_edges(*mesh, true, false);
137
138 bool verbose_validate = false;
139#ifndef NDEBUG
140 verbose_validate = true;
141#endif
142 BKE_mesh_validate(mesh, verbose_validate, false);
143 }
144
145 if (set_custom_normals_for_verts) {
147 mesh, reinterpret_cast<float(*)[3]>(data.vertex_normals.data()));
148 }
149
150 /* Merge all vertices on the same location. */
151 if (params.merge_verts) {
152 std::optional<Mesh *> merged_mesh = blender::geometry::mesh_merge_by_distance_all(
153 *mesh, IndexMask(mesh->verts_num), 0.0001f);
154 if (merged_mesh) {
155 BKE_id_free(nullptr, &mesh->id);
156 mesh = *merged_mesh;
157 }
158 }
159
160 return mesh;
161}
162} // namespace blender::io::ply
void BKE_id_attributes_default_color_set(struct ID *id, const char *name)
Definition attribute.cc:994
void BKE_id_attributes_active_color_set(struct ID *id, const char *name)
Definition attribute.cc:965
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)
void BKE_mesh_set_custom_normals_from_verts(Mesh *mesh, float(*r_custom_vert_normals)[3])
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])
@ PLY_VERTEX_COLOR_NONE
Definition IO_ply.hh:22
@ PLY_VERTEX_COLOR_SRGB
Definition IO_ply.hh:23
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
constexpr T & first() const
Definition BLI_span.hh:680
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
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)
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)
unsigned int uint32_t
Definition stdint.h:80
signed int int32_t
Definition stdint.h:77