16#include "fast_float.h"
41static const char *
drop_plus(
const char *p,
const char *end)
43 if (p < end && *p ==
'+') {
49static const char *
parse_float(
const char *p,
const char *end,
float fallback,
float &dst)
53 fast_float::from_chars_result res = fast_float::from_chars(p, end, dst);
54 if (
ELEM(res.ec, std::errc::invalid_argument, std::errc::result_out_of_range)) {
60static const char *
parse_int(
const char *p,
const char *end,
int fallback,
int &dst)
64 std::from_chars_result res = std::from_chars(p, end, dst);
65 if (
ELEM(res.ec, std::errc::invalid_argument, std::errc::result_out_of_range)) {
76 else if (type_size == 4) {
79 else if (type_size == 8) {
89 else if (type_size == 4) {
92 else if (type_size == 8) {
103 1.0f, 127.0f, 255.0f, 32767.0f, 65535.0f,
float(INT_MAX),
float(
UINT_MAX), 1.0f, 1.0f};
105 "PLY data type normalization factor table mismatch");
121 for (
int i = 0, n =
int(element.properties.size()); i != n; i++) {
123 if (prop.
name == property) {
133 if (line.is_empty()) {
134 return "Could not read row of ascii property";
138 const char *p = line.
data();
139 const char *end = p + line.size();
141 while (p < end && value_idx < r_values.
size()) {
144 r_values[value_idx++] = val;
180 val = *(
float *)r_ptr;
184 val = *(
double *)r_ptr;
199 if (element.stride == 0) {
200 return "Vertex/Edge element contains list properties, this is not supported";
204 if (!file.read_bytes(r_scratch.
data(), r_scratch.
size())) {
205 return "Could not read row of binary property";
211 for (
int i = 0, n =
int(element.properties.size()); i != n; i++) {
219 for (
int i = 0, n =
int(element.properties.size()); i != n; i++) {
227 return "Unknown binary ply format for vertex element";
241 int3 normal_index = {
244 int alpha_index =
get_index(element,
"alpha");
246 bool has_vertex = vertex_index.x >= 0 && vertex_index.y >= 0 && vertex_index.z >= 0;
247 bool has_color = color_index.x >= 0 && color_index.y >= 0 && color_index.z >= 0;
248 bool has_normal = normal_index.x >= 0 && normal_index.y >= 0 && normal_index.z >= 0;
249 bool has_uv = uv_index.x >= 0 && uv_index.y >= 0;
250 bool has_alpha = alpha_index >= 0;
253 return "Vertex positions are not present in the file";
257 for (
const int64_t prop_idx : element.properties.index_range()) {
258 const PlyProperty &prop = element.properties[prop_idx];
259 bool is_standard =
ELEM(
260 prop.
name,
"x",
"y",
"z",
"nx",
"ny",
"nz",
"red",
"green",
"blue",
"alpha",
"s",
"t");
264 custom_attr_indices.
append(prop_idx);
266 data->vertex_custom_attr.append(attr);
269 data->vertices.reserve(element.count);
271 data->vertex_colors.reserve(element.count);
274 data->vertex_normals.reserve(element.count);
277 data->uv_coordinates.reserve(element.count);
280 float4 color_norm = {1, 1, 1, 1};
293 scratch.
resize(element.stride);
296 for (
int i = 0; i < element.count; i++) {
298 const char *
error =
nullptr;
305 if (
error !=
nullptr) {
311 vertex3.x = value_vec[vertex_index.x];
312 vertex3.y = value_vec[vertex_index.y];
313 vertex3.z = value_vec[vertex_index.z];
314 data->vertices.
append(vertex3);
319 colors4.x = value_vec[color_index.x] / color_norm.x;
320 colors4.y = value_vec[color_index.y] / color_norm.y;
321 colors4.z = value_vec[color_index.z] / color_norm.z;
323 colors4.w = value_vec[alpha_index] / color_norm.w;
328 data->vertex_colors.append(colors4);
334 normals3.x = value_vec[normal_index.x];
335 normals3.y = value_vec[normal_index.y];
336 normals3.z = value_vec[normal_index.z];
337 data->vertex_normals.
append(normals3);
343 uvmap.x = value_vec[uv_index.x];
344 uvmap.y = value_vec[uv_index.y];
345 data->uv_coordinates.
append(uvmap);
350 float value = value_vec[custom_attr_indices[ci]];
351 data->vertex_custom_attr[ci].
data[i] = value;
384 file.read_bytes(scratch.
data(), scratch.
size());
393 int prop_index =
get_index(element,
"vertex_indices");
394 if (prop_index < 0) {
395 prop_index =
get_index(element,
"vertex_index");
397 if (prop_index < 0 && element.properties.size() == 1) {
400 if (prop_index < 0) {
401 return "Face element does not contain vertex indices property";
403 const PlyProperty &prop = element.properties[prop_index];
405 return "Face element vertex indices property must be a list";
408 data->face_vertices.reserve(element.count * 3);
409 data->face_sizes.reserve(element.count);
412 for (
int i = 0; i < element.count; i++) {
416 const char *p = line.
data();
417 const char *end = p + line.size();
421 for (
int j = 0; j < prop_index; j++) {
428 for (
int k = 0; k <
count; ++k) {
438 return "Invalid face size, must be between 1 and 255";
443 fprintf(stderr,
"PLY Importer: ignoring face %i (%i vertices)\n", i,
count);
447 for (
int j = 0; j <
count; j++) {
450 data->face_vertices.append(index);
452 data->face_sizes.append(
count);
458 for (
int i = 0; i < element.count; i++) {
462 for (
int j = 0; j < prop_index; j++) {
471 return "Invalid face size, must be between 1 and 255";
475 file.read_bytes(scratch.
data(), scratch.
size());
479 fprintf(stderr,
"PLY Importer: ignoring face %i (%i vertices)\n", i,
int(
count));
486 for (
int j = 0; j <
count; ++j) {
488 data->face_vertices.append(index);
490 data->face_sizes.append(
count);
494 for (
int j = prop_index + 1; j < element.properties.size(); j++) {
508 if (element.count != 1) {
509 return "Tristrips element should contain one row";
511 if (element.properties.size() != 1) {
512 return "Tristrips element should contain one property";
516 return "Tristrips element property must be a list";
524 const char *p = line.
data();
525 const char *end = p + line.size();
530 for (
int j = 0; j <
count; j++) {
545 file.read_bytes(scratch.
data(), scratch.
size());
550 for (
int j = 0; j <
count; ++j) {
559 for (
size_t i = 0; i < strip.
size(); i++) {
560 if (strip[i] == -1) {
564 else if (i - start >= 2) {
565 int a = strip[i - 2],
b = strip[i - 1], c = strip[i];
567 if ((i - start) & 1) {
571 if (a !=
b && a != c &&
b != c) {
572 data->face_vertices.append(a);
573 data->face_vertices.append(
b);
574 data->face_vertices.append(c);
575 data->face_sizes.append(3);
587 int prop_vertex1 =
get_index(element,
"vertex1");
588 int prop_vertex2 =
get_index(element,
"vertex2");
589 if (prop_vertex1 < 0 || prop_vertex2 < 0) {
590 return "Edge element does not contain vertex1 and vertex2 properties";
593 data->edges.reserve(element.count);
598 scratch.
resize(element.stride);
601 for (
int i = 0; i < element.count; i++) {
602 const char *
error =
nullptr;
609 if (
error !=
nullptr) {
612 int index1 = value_vec[prop_vertex1];
613 int index2 = value_vec[prop_vertex2];
614 data->edges.
append(std::make_pair(index1, index2));
624 for (
int i = 0; i < element.count; i++) {
631 for (
int i = 0; i < element.count; i++) {
632 for (
const PlyProperty &prop : element.properties) {
642 std::unique_ptr<PlyData> data = std::make_unique<PlyData>();
644 bool got_vertex =
false, got_face =
false, got_tristrips =
false, got_edge =
false;
646 const char *
error =
nullptr;
647 if (element.name ==
"vertex") {
651 else if (element.name ==
"face") {
655 else if (element.name ==
"tristrips") {
657 got_tristrips =
true;
659 else if (element.name ==
"edge") {
666 if (
error !=
nullptr) {
670 if (got_vertex && got_face && got_tristrips && got_edge) {
#define BLI_assert_msg(a, msg)
BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) ATTR_NONNULL(1)
BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val) ATTR_NONNULL(1)
void BLI_endian_switch_uint16_array(unsigned short *val, int size) ATTR_NONNULL(1)
BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) ATTR_NONNULL(1)
void BLI_endian_switch_uint64_array(uint64_t *val, int size) ATTR_NONNULL(1)
void BLI_endian_switch_uint32_array(unsigned int *val, int size) ATTR_NONNULL(1)
constexpr const T * data() const
void append(const T &value)
IndexRange index_range() const
void resize(const int64_t new_size)
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
static void error(const char *str)
static const char * load_face_element(PlyReadBuffer &file, const PlyHeader &header, const PlyElement &element, PlyData *data)
static const char * load_edge_element(PlyReadBuffer &file, const PlyHeader &header, const PlyElement &element, PlyData *data)
static const char * parse_row_ascii(PlyReadBuffer &file, Vector< float > &r_values)
static const char * parse_row_binary(PlyReadBuffer &file, const PlyHeader &header, const PlyElement &element, Vector< uint8_t > &r_scratch, Vector< float > &r_values)
static const char * load_vertex_element(PlyReadBuffer &file, const PlyHeader &header, const PlyElement &element, PlyData *data)
static uint32_t read_list_count(PlyReadBuffer &file, const PlyProperty &prop, Vector< uint8_t > &scratch, bool big_endian)
static const char * load_tristrips_element(PlyReadBuffer &file, const PlyHeader &header, const PlyElement &element, PlyData *data)
static int get_index(const PlyElement &element, StringRef property)
std::unique_ptr< PlyData > import_ply_data(PlyReadBuffer &file, PlyHeader &header)
static const int data_type_size[]
static const float data_type_normalizer[]
static void skip_property(PlyReadBuffer &file, const PlyProperty &prop, Vector< uint8_t > &scratch, bool big_endian)
static T get_binary_value(PlyDataTypes type, const uint8_t *&r_ptr)
static const char * skip_element(PlyReadBuffer &file, const PlyHeader &header, const PlyElement &element)
static void endian_switch_array(uint8_t *ptr, int type_size, int size)
static void endian_switch(uint8_t *ptr, int type_size)
static const char * drop_plus(const char *p, const char *end)
static const char * parse_int(const char *p, const char *end, int fallback, int &dst)
static const char * drop_whitespace(const char *p, const char *end)
static bool is_whitespace(char c)
static const char * parse_float(const char *p, const char *end, float fallback, float &dst)
static const char * drop_non_whitespace(const char *p, const char *end)
unsigned __int64 uint64_t
Vector< PlyProperty > properties