16#include "fast_float.h"
44static const char *
drop_plus(
const char *p,
const char *end)
46 if (p < end && *p ==
'+') {
52static const char *
parse_float(
const char *p,
const char *end,
float fallback,
float &dst)
56 fast_float::from_chars_result res = fast_float::from_chars(p, end, dst);
57 if (
ELEM(res.ec, std::errc::invalid_argument, std::errc::result_out_of_range)) {
63static const char *
parse_int(
const char *p,
const char *end,
int fallback,
int &dst)
67 std::from_chars_result res = std::from_chars(p, end, dst);
68 if (
ELEM(res.ec, std::errc::invalid_argument, std::errc::result_out_of_range)) {
79 else if (type_size == 4) {
82 else if (type_size == 8) {
92 else if (type_size == 4) {
95 else if (type_size == 8) {
106 1.0f, 127.0f, 255.0f, 32767.0f, 65535.0f,
float(INT_MAX),
float(
UINT_MAX), 1.0f, 1.0f};
108 "PLY data type normalization factor table mismatch");
124 for (
int i = 0, n =
int(
element.properties.size());
i != n;
i++) {
126 if (prop.
name == property) {
137 return "Could not read row of ASCII property";
141 const char *p = line.
data();
142 const char *end = p + line.
size();
144 while (p < end && value_idx < r_values.
size()) {
147 r_values[value_idx++] = val;
159 val = *(int8_t *)r_ptr;
163 val = *(uint8_t *)r_ptr;
167 val = *(int16_t *)r_ptr;
171 val = *(uint16_t *)r_ptr;
183 val = *(
float *)r_ptr;
187 val = *(
double *)r_ptr;
203 return "Vertex/Edge element contains list properties, this is not supported";
208 return "Could not read row of binary property";
211 const uint8_t *
ptr = r_scratch.
data();
214 for (
int i = 0, n =
int(
element.properties.size());
i != n;
i++) {
222 for (
int i = 0, n =
int(
element.properties.size());
i != n;
i++) {
230 return "Unknown binary ply format for vertex element";
244 int3 normal_index = {
249 bool has_vertex = vertex_index.x >= 0 && vertex_index.y >= 0 && vertex_index.z >= 0;
250 bool has_color = color_index.x >= 0 && color_index.y >= 0 && color_index.z >= 0;
251 bool has_normal = normal_index.x >= 0 && normal_index.y >= 0 && normal_index.z >= 0;
252 bool has_uv = uv_index.x >= 0 && uv_index.y >= 0;
253 bool has_alpha = alpha_index >= 0;
256 return "Vertex positions are not present in the file";
262 bool is_standard =
ELEM(
263 prop.
name,
"x",
"y",
"z",
"nx",
"ny",
"nz",
"red",
"green",
"blue",
"alpha",
"s",
"t");
268 custom_attr_indices.
append(prop_idx);
270 data->vertex_custom_attr.append(attr);
284 float4 color_norm = {1, 1, 1, 1};
302 const char *
error =
nullptr;
309 if (
error !=
nullptr) {
315 vertex3.x = value_vec[vertex_index.x];
316 vertex3.y = value_vec[vertex_index.y];
317 vertex3.z = value_vec[vertex_index.z];
318 data->vertices.append(vertex3);
323 colors4.x = value_vec[color_index.x] / color_norm.x;
324 colors4.y = value_vec[color_index.y] / color_norm.y;
325 colors4.z = value_vec[color_index.z] / color_norm.z;
327 colors4.w = value_vec[alpha_index] / color_norm.w;
332 data->vertex_colors.append(colors4);
338 normals3.x = value_vec[normal_index.x];
339 normals3.y = value_vec[normal_index.y];
340 normals3.z = value_vec[normal_index.z];
341 data->vertex_normals.append(normals3);
347 uvmap.x = value_vec[uv_index.x];
348 uvmap.y = value_vec[uv_index.y];
349 data->uv_coordinates.append(uvmap);
354 float value = value_vec[custom_attr_indices[ci]];
355 data->vertex_custom_attr[ci].data[
i] = value;
368 const uint8_t *
ptr = scratch.
data();
398 if (prop_index < 0) {
401 if (prop_index < 0 &&
element.properties.size() == 1) {
404 if (prop_index < 0) {
405 return "Face element does not contain vertex indices property";
409 return "Face element vertex indices property must be a list";
420 const char *p = line.
data();
421 const char *end = p + line.
size();
425 for (
int j = 0; j < prop_index; j++) {
432 for (
int k = 0; k <
count; ++k) {
442 return "Invalid face size, must be between 1 and 255";
451 for (
int j = 0; j <
count; j++) {
454 data->face_vertices.append(index);
466 for (
int j = 0; j < prop_index; j++) {
475 return "Invalid face size, must be between 1 and 255";
490 for (
int j = 0; j <
count; ++j) {
492 data->face_vertices.append(index);
498 for (
int j = prop_index + 1; j <
element.properties.size(); j++) {
513 return "Tristrips element should contain one row";
515 if (
element.properties.size() != 1) {
516 return "Tristrips element should contain one property";
520 return "Tristrips element property must be a list";
528 const char *p = line.
data();
529 const char *end = p + line.
size();
534 for (
int j = 0; j <
count; j++) {
554 for (
int j = 0; j <
count; ++j) {
563 for (
size_t i = 0;
i < strip.
size();
i++) {
564 if (strip[
i] == -1) {
568 else if (
i - start >= 2) {
569 int a = strip[
i - 2],
b = strip[
i - 1], c = strip[
i];
571 if ((
i - start) & 1) {
575 if (a !=
b && a != c &&
b != c) {
576 data->face_vertices.append(a);
577 data->face_vertices.append(
b);
578 data->face_vertices.append(c);
579 data->face_sizes.append(3);
593 if (prop_vertex1 < 0 || prop_vertex2 < 0) {
594 return "Edge element does not contain vertex1 and vertex2 properties";
606 const char *
error =
nullptr;
613 if (
error !=
nullptr) {
616 int index1 = value_vec[prop_vertex1];
617 int index2 = value_vec[prop_vertex2];
618 data->edges.append(std::make_pair(index1, index2));
646 std::unique_ptr<PlyData>
data = std::make_unique<PlyData>();
648 bool got_vertex =
false, got_face =
false, got_tristrips =
false, got_edge =
false;
650 const char *
error =
nullptr;
651 if (
element.name ==
"vertex") {
655 else if (
element.name ==
"face") {
659 else if (
element.name ==
"tristrips") {
661 got_tristrips =
true;
663 else if (
element.name ==
"edge") {
670 if (
error !=
nullptr) {
674 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)
#define CLOG_WARN(clg_ref,...)
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const void * element
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
constexpr const T * data() const
constexpr int64_t size() const
constexpr bool is_empty() const
void append(const T &value)
IndexRange index_range() const
void resize(const int64_t new_size)
bool read_bytes(void *dst, size_t size)
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)
const char * parse_float(const char *p, const char *end, float fallback, float &dst, bool skip_space, bool require_trailing_space)
const char * drop_non_whitespace(const char *p, const char *end)
const char * parse_int(const char *p, const char *end, int fallback, int &dst, bool skip_space)
const char * drop_whitespace(const char *p, const char *end)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
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)
Vector< PlyProperty > properties