forked from blender/blender
Implemented feedback from Hans and Aras #2
@ -77,7 +77,7 @@ static void ui_ply_export_settings(uiLayout *layout, PointerRNA *imfptr)
|
|||||||
uiLayoutSetPropSep(layout, true);
|
uiLayoutSetPropSep(layout, true);
|
||||||
uiLayoutSetPropDecorate(layout, false);
|
uiLayoutSetPropDecorate(layout, false);
|
||||||
|
|
||||||
uiLayout *box, *col, *sub, *row;
|
uiLayout *box, *col, *sub;
|
||||||
|
|
||||||
/* Object Transform options. */
|
/* Object Transform options. */
|
||||||
box = uiLayoutBox(layout);
|
box = uiLayoutBox(layout);
|
||||||
@ -88,10 +88,8 @@ static void ui_ply_export_settings(uiLayout *layout, PointerRNA *imfptr)
|
|||||||
uiItemR(sub, imfptr, "export_selected_objects", 0, IFACE_("Selected Only"), ICON_NONE);
|
uiItemR(sub, imfptr, "export_selected_objects", 0, IFACE_("Selected Only"), ICON_NONE);
|
||||||
uiItemR(sub, imfptr, "global_scale", 0, NULL, ICON_NONE);
|
uiItemR(sub, imfptr, "global_scale", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
row = uiLayoutRow(box, false);
|
uiItemR(sub, imfptr, "forward_axis", 0, IFACE_("Forward Axis"), ICON_NONE);
|
||||||
uiItemR(row, imfptr, "forward_axis", 0, IFACE_("Forward Axis"), ICON_NONE);
|
uiItemR(sub, imfptr, "up_axis", 0, IFACE_("Up Axis"), ICON_NONE);
|
||||||
row = uiLayoutRow(box, false);
|
|
||||||
uiItemR(row, imfptr, "up_axis", 0, IFACE_("Up Axis"), ICON_NONE);
|
|
||||||
|
|
||||||
col = uiLayoutColumn(box, false);
|
col = uiLayoutColumn(box, false);
|
||||||
sub = uiLayoutColumn(col, false);
|
sub = uiLayoutColumn(col, false);
|
||||||
|
@ -23,29 +23,33 @@ set(INC_SYS
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(SRC
|
set(SRC
|
||||||
IO_ply.cc
|
|
||||||
exporter/ply_export.cc
|
|
||||||
importer/ply_import.cc
|
|
||||||
importer/ply_import_binary.cc
|
|
||||||
importer/ply_import_ascii.cc
|
|
||||||
importer/ply_import_mesh.cc
|
|
||||||
exporter/ply_export_header.cc
|
|
||||||
exporter/ply_export_data.cc
|
exporter/ply_export_data.cc
|
||||||
|
exporter/ply_export_header.cc
|
||||||
exporter/ply_export_load_plydata.cc
|
exporter/ply_export_load_plydata.cc
|
||||||
|
exporter/ply_export.cc
|
||||||
|
exporter/ply_file_buffer_ascii.cc
|
||||||
|
exporter/ply_file_buffer_binary.cc
|
||||||
|
exporter/ply_file_buffer.cc
|
||||||
|
importer/ply_import_ascii.cc
|
||||||
|
importer/ply_import_binary.cc
|
||||||
|
importer/ply_import_mesh.cc
|
||||||
|
importer/ply_import.cc
|
||||||
|
IO_ply.cc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
IO_ply.h
|
|
||||||
exporter/ply_export.hh
|
|
||||||
exporter/ply_export_header.hh
|
|
||||||
exporter/ply_export_data.hh
|
exporter/ply_export_data.hh
|
||||||
|
exporter/ply_export_header.hh
|
||||||
|
exporter/ply_export_load_plydata.hh
|
||||||
|
exporter/ply_export.hh
|
||||||
exporter/ply_file_buffer_ascii.hh
|
exporter/ply_file_buffer_ascii.hh
|
||||||
exporter/ply_file_buffer_binary.hh
|
exporter/ply_file_buffer_binary.hh
|
||||||
exporter/ply_export_load_plydata.hh
|
exporter/ply_file_buffer.hh
|
||||||
importer/ply_import.hh
|
|
||||||
importer/ply_import_binary.hh
|
|
||||||
importer/ply_import_ascii.hh
|
importer/ply_import_ascii.hh
|
||||||
|
importer/ply_import_binary.hh
|
||||||
importer/ply_import_mesh.hh
|
importer/ply_import_mesh.hh
|
||||||
|
importer/ply_import.hh
|
||||||
|
IO_ply.h
|
||||||
|
|
||||||
intern/ply_data.hh
|
intern/ply_data.hh
|
||||||
intern/ply_functions.hh
|
intern/ply_functions.hh
|
||||||
|
@ -35,11 +35,9 @@ void exporter_main(Main *bmain,
|
|||||||
bContext *C,
|
bContext *C,
|
||||||
const PLYExportParams &export_params)
|
const PLYExportParams &export_params)
|
||||||
{
|
{
|
||||||
/* Load mesh data into PlyData struct. */
|
|
||||||
std::unique_ptr<blender::io::ply::PlyData> plyData = std::make_unique<PlyData>();
|
std::unique_ptr<blender::io::ply::PlyData> plyData = std::make_unique<PlyData>();
|
||||||
load_plydata(*plyData, CTX_data_ensure_evaluated_depsgraph(C), export_params);
|
load_plydata(*plyData, CTX_data_ensure_evaluated_depsgraph(C), export_params);
|
||||||
|
|
||||||
/* Get filebuffer. */
|
|
||||||
std::unique_ptr<FileBuffer> buffer;
|
std::unique_ptr<FileBuffer> buffer;
|
||||||
|
|
||||||
if (export_params.ascii_format) {
|
if (export_params.ascii_format) {
|
||||||
@ -49,19 +47,14 @@ void exporter_main(Main *bmain,
|
|||||||
buffer = std::make_unique<FileBufferBinary>(export_params.filepath);
|
buffer = std::make_unique<FileBufferBinary>(export_params.filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate and write header. */
|
|
||||||
write_header(*buffer.get(), *plyData.get(), export_params);
|
write_header(*buffer.get(), *plyData.get(), export_params);
|
||||||
|
|
||||||
/* Generate and write vertices. */
|
|
||||||
write_vertices(*buffer.get(), *plyData.get());
|
write_vertices(*buffer.get(), *plyData.get());
|
||||||
|
|
||||||
/* Generate and write faces. */
|
|
||||||
write_faces(*buffer.get(), *plyData.get());
|
write_faces(*buffer.get(), *plyData.get());
|
||||||
|
|
||||||
/* Generate and write edges. */
|
|
||||||
write_edges(*buffer.get(), *plyData.get());
|
write_edges(*buffer.get(), *plyData.get());
|
||||||
|
|
||||||
/* Clean up. */
|
|
||||||
buffer->close_file();
|
buffer->close_file();
|
||||||
}
|
}
|
||||||
} // namespace blender::io::ply
|
} // namespace blender::io::ply
|
||||||
|
@ -174,7 +174,7 @@ void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams
|
|||||||
const Span<float3> vert_normals = mesh->vertex_normals();
|
const Span<float3> vert_normals = mesh->vertex_normals();
|
||||||
for (int i = 0; i < vertex_map.size(); i++) {
|
for (int i = 0; i < vertex_map.size(); i++) {
|
||||||
mul_m3_v3(world_and_axes_normal_transform_,
|
mul_m3_v3(world_and_axes_normal_transform_,
|
||||||
(float3)vert_normals[mesh_vertex_index_LUT[i]]);
|
float3(vert_normals[mesh_vertex_index_LUT[i]]));
|
||||||
plyData.vertex_normals.append(vert_normals[mesh_vertex_index_LUT[i]]);
|
plyData.vertex_normals.append(vert_normals[mesh_vertex_index_LUT[i]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
82
source/blender/io/ply/exporter/ply_file_buffer.cc
Normal file
82
source/blender/io/ply/exporter/ply_file_buffer.cc
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup ply
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ply_file_buffer.hh"
|
||||||
|
|
||||||
|
namespace blender::io::ply {
|
||||||
|
|
||||||
|
FileBuffer::FileBuffer(const char *filepath, size_t buffer_chunk_size)
|
||||||
|
: buffer_chunk_size_(buffer_chunk_size), filepath_(filepath)
|
||||||
|
{
|
||||||
|
outfile_ = BLI_fopen(filepath, "wb");
|
||||||
|
if (!outfile_) {
|
||||||
|
throw std::system_error(
|
||||||
|
errno, std::system_category(), "Cannot open file " + std::string(filepath) + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBuffer::write_to_file()
|
||||||
|
{
|
||||||
|
for (const VectorChar &b : blocks_)
|
||||||
|
fwrite(b.data(), 1, b.size(), this->outfile_);
|
||||||
|
blocks_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBuffer::close_file()
|
||||||
|
{
|
||||||
|
int close_status = std::fclose(outfile_);
|
||||||
|
if (close_status == EOF) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (outfile_ && close_status) {
|
||||||
|
std::cerr << "Error: could not close the file '" << this->filepath_
|
||||||
|
<< "' properly, it may be corrupted." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBuffer::write_header_element(StringRef name, int count)
|
||||||
|
{
|
||||||
|
write_fstring("element {} {}\n", name, count);
|
||||||
|
}
|
||||||
|
void FileBuffer::write_header_scalar_property(StringRef dataType, StringRef name)
|
||||||
|
{
|
||||||
|
write_fstring("property {} {}\n", dataType, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBuffer::write_header_list_property(StringRef countType,
|
||||||
|
StringRef dataType,
|
||||||
|
StringRef name)
|
||||||
|
{
|
||||||
|
write_fstring("property list {} {} {}\n", countType, dataType, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBuffer::write_string(StringRef s)
|
||||||
|
{
|
||||||
|
write_fstring("{}\n", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBuffer::write_newline()
|
||||||
|
{
|
||||||
|
write_fstring("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBuffer::ensure_space(size_t at_least)
|
||||||
|
{
|
||||||
|
if (blocks_.is_empty() || (blocks_.last().capacity() - blocks_.last().size() < at_least)) {
|
||||||
|
|
||||||
|
blocks_.append(VectorChar());
|
||||||
|
blocks_.reserve(std::max(at_least, buffer_chunk_size_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBuffer::write_bytes(Span<char> bytes)
|
||||||
|
{
|
||||||
|
ensure_space(bytes.size());
|
||||||
|
VectorChar &bb = blocks_.last();
|
||||||
|
bb.insert(bb.end(), bytes.begin(), bytes.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::io::ply
|
@ -28,11 +28,10 @@ namespace blender::io::ply {
|
|||||||
* File buffer writer.
|
* File buffer writer.
|
||||||
* All writes are done into an internal chunked memory buffer
|
* All writes are done into an internal chunked memory buffer
|
||||||
* (list of default 64 kilobyte blocks).
|
* (list of default 64 kilobyte blocks).
|
||||||
* Call write_fo_file once in a while to write the memory buffer(s)
|
* Call write_to_file once in a while to write the memory buffer(s)
|
||||||
* into the given file.
|
* into the given file.
|
||||||
*/
|
*/
|
||||||
class FileBuffer : private NonMovable {
|
class FileBuffer : private NonMovable {
|
||||||
private:
|
|
||||||
using VectorChar = Vector<char>;
|
using VectorChar = Vector<char>;
|
||||||
Vector<VectorChar> blocks_;
|
Vector<VectorChar> blocks_;
|
||||||
size_t buffer_chunk_size_;
|
size_t buffer_chunk_size_;
|
||||||
@ -40,57 +39,14 @@ class FileBuffer : private NonMovable {
|
|||||||
FILE *outfile_;
|
FILE *outfile_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileBuffer(const char *filepath, size_t buffer_chunk_size = 64 * 1024)
|
FileBuffer(const char *filepath, size_t buffer_chunk_size = 64 * 1024);
|
||||||
: buffer_chunk_size_(buffer_chunk_size), filepath_(filepath)
|
|
||||||
{
|
|
||||||
outfile_ = BLI_fopen(filepath, "wb");
|
|
||||||
if (!outfile_) {
|
|
||||||
throw std::system_error(
|
|
||||||
errno, std::system_category(), "Cannot open file " + std::string(filepath) + ".");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~FileBuffer() = default;
|
virtual ~FileBuffer() = default;
|
||||||
|
|
||||||
/* Write contents to the buffer(s) into a file, and clear the buffers. */
|
/* Write contents to the buffer(s) into a file, and clear the buffers. */
|
||||||
void write_to_file()
|
void write_to_file();
|
||||||
{
|
|
||||||
for (const auto &b : blocks_)
|
|
||||||
fwrite(b.data(), 1, b.size(), this->outfile_);
|
|
||||||
blocks_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void close_file()
|
void close_file();
|
||||||
{
|
|
||||||
auto close_status = std::fclose(outfile_);
|
|
||||||
if (close_status == EOF) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (outfile_ && close_status) {
|
|
||||||
std::cerr << "Error: could not close the file '" << this->filepath_
|
|
||||||
<< "' properly, it may be corrupted." << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string get_as_string() const
|
|
||||||
{
|
|
||||||
std::string s;
|
|
||||||
for (const auto &b : blocks_)
|
|
||||||
s.append(b.data(), b.size());
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
size_t get_block_count() const
|
|
||||||
{
|
|
||||||
return blocks_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void append_from(FileBuffer &v)
|
|
||||||
{
|
|
||||||
blocks_.insert(blocks_.end(),
|
|
||||||
std::make_move_iterator(v.blocks_.begin()),
|
|
||||||
std::make_move_iterator(v.blocks_.end()));
|
|
||||||
v.blocks_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void write_vertex(float x, float y, float z) = 0;
|
virtual void write_vertex(float x, float y, float z) = 0;
|
||||||
|
|
||||||
@ -106,41 +62,20 @@ class FileBuffer : private NonMovable {
|
|||||||
|
|
||||||
virtual void write_edge(int first, int second) = 0;
|
virtual void write_edge(int first, int second) = 0;
|
||||||
|
|
||||||
void write_header_element(StringRef name, int count)
|
void write_header_element(StringRef name, int count);
|
||||||
{
|
|
||||||
write_fstring("element {} {}\n", name, count);
|
|
||||||
}
|
|
||||||
void write_header_scalar_property(StringRef dataType, StringRef name)
|
|
||||||
{
|
|
||||||
write_fstring("property {} {}\n", dataType, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_header_list_property(StringRef countType, StringRef dataType, StringRef name)
|
void write_header_scalar_property(StringRef dataType, StringRef name);
|
||||||
{
|
|
||||||
write_fstring("property list {} {} {}\n", countType, dataType, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_string(StringRef s)
|
void write_header_list_property(StringRef countType, StringRef dataType, StringRef name);
|
||||||
{
|
|
||||||
write_fstring("{}\n", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_newline()
|
void write_string(StringRef s);
|
||||||
{
|
|
||||||
write_fstring("\n");
|
void write_newline();
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* Ensure the last block contains at least this amount of free space.
|
/* Ensure the last block contains at least this amount of free space.
|
||||||
* If not, add a new block with max of block size & the amount of space needed. */
|
* If not, add a new block with max of block size & the amount of space needed. */
|
||||||
void ensure_space(size_t at_least)
|
void ensure_space(size_t at_least);
|
||||||
{
|
|
||||||
if (blocks_.is_empty() || (blocks_.last().capacity() - blocks_.last().size() < at_least)) {
|
|
||||||
|
|
||||||
blocks_.append(VectorChar());
|
|
||||||
blocks_.reserve(std::max(at_least, buffer_chunk_size_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... T> void write_fstring(const char *fmt, T &&...args)
|
template<typename... T> void write_fstring(const char *fmt, T &&...args)
|
||||||
{
|
{
|
||||||
@ -153,12 +88,7 @@ class FileBuffer : private NonMovable {
|
|||||||
bb.insert(bb.end(), buf.begin(), buf.end());
|
bb.insert(bb.end(), buf.begin(), buf.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_bytes(Span<char> bytes)
|
void write_bytes(Span<char> bytes);
|
||||||
{
|
|
||||||
ensure_space(bytes.size());
|
|
||||||
VectorChar &bb = blocks_.last();
|
|
||||||
bb.insert(bb.end(), bytes.begin(), bytes.end());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::io::ply
|
} // namespace blender::io::ply
|
||||||
|
51
source/blender/io/ply/exporter/ply_file_buffer_ascii.cc
Normal file
51
source/blender/io/ply/exporter/ply_file_buffer_ascii.cc
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup ply
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ply_file_buffer_ascii.hh"
|
||||||
|
|
||||||
|
namespace blender::io::ply {
|
||||||
|
|
||||||
|
void FileBufferAscii::write_vertex(float x, float y, float z)
|
||||||
|
{
|
||||||
|
write_fstring("{} {} {}", x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferAscii::write_UV(float u, float v)
|
||||||
|
{
|
||||||
|
write_fstring(" {} {}", u, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferAscii::write_vertex_normal(float nx, float ny, float nz)
|
||||||
|
{
|
||||||
|
write_fstring(" {} {} {}", nx, ny, nz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferAscii::write_vertex_color(uchar r, uchar g, uchar b, uchar a)
|
||||||
|
{
|
||||||
|
write_fstring(" {} {} {} {}", r, g, b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferAscii::write_vertex_end()
|
||||||
|
{
|
||||||
|
write_fstring("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferAscii::write_face(char count, Array<uint32_t> const &vertex_indices)
|
||||||
|
{
|
||||||
|
write_fstring("{}", int(count));
|
||||||
|
|
||||||
|
for (const uint32_t v : vertex_indices) {
|
||||||
|
write_fstring(" {}", v);
|
||||||
|
}
|
||||||
|
write_newline();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferAscii::write_edge(int first, int second)
|
||||||
|
{
|
||||||
|
write_fstring("{} {}", first, second);
|
||||||
|
write_newline();
|
||||||
|
}
|
||||||
|
} // namespace blender::io::ply
|
@ -6,65 +6,25 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include "BLI_array.hh"
|
|
||||||
#include "BLI_compiler_attrs.h"
|
|
||||||
#include "BLI_fileops.h"
|
|
||||||
#include "BLI_string_ref.hh"
|
|
||||||
#include "BLI_utility_mixins.hh"
|
|
||||||
|
|
||||||
#include "ply_file_buffer.hh"
|
#include "ply_file_buffer.hh"
|
||||||
|
|
||||||
/* SEP macro from BLI path utils clashes with SEP symbol in fmt headers. */
|
|
||||||
#undef SEP
|
|
||||||
#define FMT_HEADER_ONLY
|
|
||||||
#include <fmt/format.h>
|
|
||||||
|
|
||||||
namespace blender::io::ply {
|
namespace blender::io::ply {
|
||||||
class FileBufferAscii : public FileBuffer {
|
class FileBufferAscii : public FileBuffer {
|
||||||
public:
|
|
||||||
using FileBuffer::FileBuffer;
|
using FileBuffer::FileBuffer;
|
||||||
|
|
||||||
void write_vertex(float x, float y, float z) override
|
public:
|
||||||
{
|
void write_vertex(float x, float y, float z) override;
|
||||||
write_fstring("{} {} {}", x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_UV(float u, float v) override
|
void write_UV(float u, float v) override;
|
||||||
{
|
|
||||||
write_fstring(" {} {}", u, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_vertex_normal(float nx, float ny, float nz) override
|
void write_vertex_normal(float nx, float ny, float nz) override;
|
||||||
{
|
|
||||||
write_fstring(" {} {} {}", nx, ny, nz);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_vertex_color(uchar r, uchar g, uchar b, uchar a) override
|
void write_vertex_color(uchar r, uchar g, uchar b, uchar a) override;
|
||||||
{
|
|
||||||
write_fstring(" {} {} {} {}", r, g, b, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_vertex_end() override
|
void write_vertex_end() override;
|
||||||
{
|
|
||||||
write_fstring("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_face(char count, Array<uint32_t> const &vertex_indices) override
|
void write_face(char count, Array<uint32_t> const &vertex_indices) override;
|
||||||
{
|
|
||||||
write_fstring("{}", int(count));
|
|
||||||
|
|
||||||
for (auto &&v : vertex_indices) {
|
void write_edge(int first, int second) override;
|
||||||
write_fstring(" {}", v);
|
|
||||||
}
|
|
||||||
write_newline();
|
|
||||||
}
|
|
||||||
void write_edge(int first, int second) override
|
|
||||||
{
|
|
||||||
write_fstring("{} {}", first, second);
|
|
||||||
write_newline();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
} // namespace blender::io::ply
|
} // namespace blender::io::ply
|
||||||
|
68
source/blender/io/ply/exporter/ply_file_buffer_binary.cc
Normal file
68
source/blender/io/ply/exporter/ply_file_buffer_binary.cc
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup ply
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ply_file_buffer_binary.hh"
|
||||||
|
|
||||||
|
namespace blender::io::ply {
|
||||||
|
void FileBufferBinary::write_vertex(float x, float y, float z)
|
||||||
|
{
|
||||||
|
float3 vector(x, y, z);
|
||||||
|
char *bits = reinterpret_cast<char *>(&vector);
|
||||||
|
Span<char> span(bits, sizeof(float3));
|
||||||
|
|
||||||
|
write_bytes(span);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferBinary::write_UV(float u, float v)
|
||||||
|
{
|
||||||
|
float2 vector(u, v);
|
||||||
|
char *bits = reinterpret_cast<char *>(&vector);
|
||||||
|
Span<char> span(bits, sizeof(float2));
|
||||||
|
|
||||||
|
write_bytes(span);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferBinary::write_vertex_normal(float nx, float ny, float nz)
|
||||||
|
{
|
||||||
|
float3 vector(nx, ny, nz);
|
||||||
|
char *bits = reinterpret_cast<char *>(&vector);
|
||||||
|
Span<char> span(bits, sizeof(float3));
|
||||||
|
|
||||||
|
write_bytes(span);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferBinary::write_vertex_color(uchar r, uchar g, uchar b, uchar a)
|
||||||
|
{
|
||||||
|
uchar4 vector(r, g, b, a);
|
||||||
|
char *bits = reinterpret_cast<char *>(&vector);
|
||||||
|
Span<char> span(bits, sizeof(uchar4));
|
||||||
|
|
||||||
|
write_bytes(span);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferBinary::write_vertex_end()
|
||||||
|
{
|
||||||
|
/* In binary, there is no end to a vertex. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferBinary::write_face(char size, Array<uint32_t> const &vertex_indices)
|
||||||
|
{
|
||||||
|
write_bytes(Span<char>({size}));
|
||||||
|
|
||||||
|
Span<char> dataSpan(reinterpret_cast<const char *>(vertex_indices.data()),
|
||||||
|
vertex_indices.size() * sizeof(uint32_t));
|
||||||
|
write_bytes(dataSpan);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferBinary::write_edge(int first, int second)
|
||||||
|
{
|
||||||
|
int2 vector(first, second);
|
||||||
|
char *bits = reinterpret_cast<char *>(&vector);
|
||||||
|
Span<char> span(bits, sizeof(int2));
|
||||||
|
|
||||||
|
write_bytes(span);
|
||||||
|
}
|
||||||
|
} // namespace blender::io::ply
|
@ -18,74 +18,25 @@
|
|||||||
|
|
||||||
#include "ply_file_buffer.hh"
|
#include "ply_file_buffer.hh"
|
||||||
|
|
||||||
/* SEP macro from BLI path utils clashes with SEP symbol in fmt headers. */
|
|
||||||
#undef SEP
|
|
||||||
#define FMT_HEADER_ONLY
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <fmt/format.h>
|
|
||||||
|
|
||||||
namespace blender::io::ply {
|
namespace blender::io::ply {
|
||||||
class FileBufferBinary : public FileBuffer {
|
class FileBufferBinary : public FileBuffer {
|
||||||
public:
|
|
||||||
using FileBuffer::FileBuffer;
|
using FileBuffer::FileBuffer;
|
||||||
|
|
||||||
void write_vertex(float x, float y, float z) override
|
public:
|
||||||
{
|
void write_vertex(float x, float y, float z) override;
|
||||||
float3 vector(x, y, z);
|
|
||||||
char *bits = reinterpret_cast<char *>(&vector);
|
|
||||||
Span<char> span(bits, sizeof(float3));
|
|
||||||
|
|
||||||
write_bytes(span);
|
void write_UV(float u, float v) override;
|
||||||
}
|
|
||||||
|
|
||||||
void write_UV(float u, float v) override
|
void write_vertex_normal(float nx, float ny, float nz) override;
|
||||||
{
|
|
||||||
float2 vector(u, v);
|
|
||||||
char *bits = reinterpret_cast<char *>(&vector);
|
|
||||||
Span<char> span(bits, sizeof(float2));
|
|
||||||
|
|
||||||
write_bytes(span);
|
void write_vertex_color(uchar r, uchar g, uchar b, uchar a) override;
|
||||||
}
|
|
||||||
|
|
||||||
void write_vertex_normal(float nx, float ny, float nz) override
|
void write_vertex_end() override;
|
||||||
{
|
|
||||||
float3 vector(nx, ny, nz);
|
|
||||||
char *bits = reinterpret_cast<char *>(&vector);
|
|
||||||
Span<char> span(bits, sizeof(float3));
|
|
||||||
|
|
||||||
write_bytes(span);
|
void write_face(char size, Array<uint32_t> const &vertex_indices) override;
|
||||||
}
|
|
||||||
|
|
||||||
void write_vertex_color(uchar r, uchar g, uchar b, uchar a) override
|
void write_edge(int first, int second) override;
|
||||||
{
|
|
||||||
uchar4 vector(r, g, b, a);
|
|
||||||
char *bits = reinterpret_cast<char *>(&vector);
|
|
||||||
Span<char> span(bits, sizeof(uchar4));
|
|
||||||
|
|
||||||
write_bytes(span);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_vertex_end() override
|
|
||||||
{
|
|
||||||
/* In binary, there is no end to a vertex. */
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_face(char size, Array<uint32_t> const &vertex_indices) override
|
|
||||||
{
|
|
||||||
write_bytes(Span<char>({size}));
|
|
||||||
|
|
||||||
Span<char> dataSpan(reinterpret_cast<const char *>(vertex_indices.data()),
|
|
||||||
vertex_indices.size() * sizeof(uint32_t));
|
|
||||||
write_bytes(dataSpan);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_edge(int first, int second) override
|
|
||||||
{
|
|
||||||
int2 vector(first, second);
|
|
||||||
char *bits = reinterpret_cast<char *>(&vector);
|
|
||||||
Span<char> span(bits, sizeof(int2));
|
|
||||||
|
|
||||||
write_bytes(span);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
} // namespace blender::io::ply
|
} // namespace blender::io::ply
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
|
|
||||||
|
#include "BLI_fileops.hh"
|
||||||
#include "BLI_math_vector.h"
|
#include "BLI_math_vector.h"
|
||||||
#include "BLI_memory_utils.hh"
|
#include "BLI_memory_utils.hh"
|
||||||
|
|
||||||
@ -86,11 +87,11 @@ void importer_main(Main *bmain,
|
|||||||
{
|
{
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
std::ifstream infile(import_params.filepath, std::ios::binary);
|
fstream infile(import_params.filepath, std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
PlyHeader header;
|
PlyHeader header;
|
||||||
|
|
||||||
while (true) { // We break when end_header is encountered.
|
while (true) { /* We break when end_header is encountered. */
|
||||||
safe_getline(infile, line);
|
safe_getline(infile, line);
|
||||||
if (header.header_size == 0 && line != "ply") {
|
if (header.header_size == 0 && line != "ply") {
|
||||||
fprintf(stderr, "PLY Importer: failed to read file. Invalid PLY header.\n");
|
fprintf(stderr, "PLY Importer: failed to read file. Invalid PLY header.\n");
|
||||||
@ -141,7 +142,6 @@ void importer_main(Main *bmain,
|
|||||||
else if ((words[0][0] >= '0' && words[0][0] <= '9') || words[0][0] == '-' || line.empty() ||
|
else if ((words[0][0] >= '0' && words[0][0] <= '9') || words[0][0] == '-' || line.empty() ||
|
||||||
infile.eof()) {
|
infile.eof()) {
|
||||||
/* A value was found before we broke out of the loop. No end_header. */
|
/* A value was found before we broke out of the loop. No end_header. */
|
||||||
fprintf(stderr, "PLY Importer: failed to read file. No end_header.\n");
|
|
||||||
BKE_report(op->reports, RPT_ERROR, "PLY Importer: No end_header");
|
BKE_report(op->reports, RPT_ERROR, "PLY Importer: No end_header");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -12,14 +12,13 @@
|
|||||||
|
|
||||||
namespace blender::io::ply {
|
namespace blender::io::ply {
|
||||||
|
|
||||||
std::unique_ptr<PlyData> import_ply_ascii(std::ifstream &file, PlyHeader *header)
|
std::unique_ptr<PlyData> import_ply_ascii(fstream &file, PlyHeader *header)
|
||||||
{
|
{
|
||||||
std::unique_ptr<PlyData> data = std::make_unique<PlyData>();
|
std::unique_ptr<PlyData> data = std::make_unique<PlyData>(load_ply_ascii(file, header));
|
||||||
*data = load_ply_ascii(file, header);
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlyData load_ply_ascii(std::ifstream &file, const PlyHeader *header)
|
PlyData load_ply_ascii(fstream &file, const PlyHeader *header)
|
||||||
{
|
{
|
||||||
PlyData data;
|
PlyData data;
|
||||||
/* Check if header contains alpha. */
|
/* Check if header contains alpha. */
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "BLI_fileops.hh"
|
||||||
|
|
||||||
#include "DNA_mesh_types.h"
|
#include "DNA_mesh_types.h"
|
||||||
|
|
||||||
#include "IO_ply.h"
|
#include "IO_ply.h"
|
||||||
@ -18,7 +20,7 @@ namespace blender::io::ply {
|
|||||||
* \param file: The PLY file that was opened.
|
* \param file: The PLY file that was opened.
|
||||||
* \param header: The information in the PLY header.
|
* \param header: The information in the PLY header.
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<PlyData> import_ply_ascii(std::ifstream &file, PlyHeader *header);
|
std::unique_ptr<PlyData> import_ply_ascii(fstream &file, PlyHeader *header);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the information from the PLY file in ASCII format to the PlyData datastructure.
|
* Loads the information from the PLY file in ASCII format to the PlyData datastructure.
|
||||||
@ -26,7 +28,7 @@ std::unique_ptr<PlyData> import_ply_ascii(std::ifstream &file, PlyHeader *header
|
|||||||
* \param header: The information in the PLY header.
|
* \param header: The information in the PLY header.
|
||||||
* \return The PlyData datastructure that can be used for conversion to a Mesh.
|
* \return The PlyData datastructure that can be used for conversion to a Mesh.
|
||||||
*/
|
*/
|
||||||
PlyData load_ply_ascii(std::ifstream &file, const PlyHeader *header);
|
PlyData load_ply_ascii(fstream &file, const PlyHeader *header);
|
||||||
|
|
||||||
int3 get_vertex_index(const PlyHeader *header);
|
int3 get_vertex_index(const PlyHeader *header);
|
||||||
int3 get_color_index(const PlyHeader *header);
|
int3 get_color_index(const PlyHeader *header);
|
||||||
|
@ -10,14 +10,13 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
namespace blender::io::ply {
|
namespace blender::io::ply {
|
||||||
std::unique_ptr<PlyData> import_ply_binary(std::ifstream &file, const PlyHeader *header)
|
std::unique_ptr<PlyData> import_ply_binary(fstream &file, const PlyHeader *header)
|
||||||
{
|
{
|
||||||
std::unique_ptr<PlyData> data = std::make_unique<PlyData>();
|
std::unique_ptr<PlyData> data = std::make_unique<PlyData>(load_ply_binary(file, header));
|
||||||
*data = load_ply_binary(file, header);
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> T read(std::ifstream &file, bool isBigEndian)
|
template<typename T> T read(fstream &file, bool isBigEndian)
|
||||||
{
|
{
|
||||||
T returnVal;
|
T returnVal;
|
||||||
file.read((char *)&returnVal, sizeof(returnVal));
|
file.read((char *)&returnVal, sizeof(returnVal));
|
||||||
@ -28,16 +27,16 @@ template<typename T> T read(std::ifstream &file, bool isBigEndian)
|
|||||||
return returnVal;
|
return returnVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
template uint8_t read<uint8_t>(std::ifstream &file, bool isBigEndian);
|
template uint8_t read<uint8_t>(fstream &file, bool isBigEndian);
|
||||||
template int8_t read<int8_t>(std::ifstream &file, bool isBigEndian);
|
template int8_t read<int8_t>(fstream &file, bool isBigEndian);
|
||||||
template uint16_t read<uint16_t>(std::ifstream &file, bool isBigEndian);
|
template uint16_t read<uint16_t>(fstream &file, bool isBigEndian);
|
||||||
template int16_t read<int16_t>(std::ifstream &file, bool isBigEndian);
|
template int16_t read<int16_t>(fstream &file, bool isBigEndian);
|
||||||
template uint32_t read<uint32_t>(std::ifstream &file, bool isBigEndian);
|
template uint32_t read<uint32_t>(fstream &file, bool isBigEndian);
|
||||||
template int32_t read<int32_t>(std::ifstream &file, bool isBigEndian);
|
template int32_t read<int32_t>(fstream &file, bool isBigEndian);
|
||||||
template float read<float>(std::ifstream &file, bool isBigEndian);
|
template float read<float>(fstream &file, bool isBigEndian);
|
||||||
template double read<double>(std::ifstream &file, bool isBigEndian);
|
template double read<double>(fstream &file, bool isBigEndian);
|
||||||
|
|
||||||
void check_file_errors(const std::ifstream &file)
|
void check_file_errors(const fstream &file)
|
||||||
{
|
{
|
||||||
if (file.bad()) {
|
if (file.bad()) {
|
||||||
throw std::ios_base::failure("Read/Write error on io operation");
|
throw std::ios_base::failure("Read/Write error on io operation");
|
||||||
@ -50,7 +49,7 @@ void check_file_errors(const std::ifstream &file)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void discard_value(std::ifstream &file, const PlyDataTypes type)
|
void discard_value(fstream &file, const PlyDataTypes type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CHAR:
|
case CHAR:
|
||||||
@ -80,7 +79,7 @@ void discard_value(std::ifstream &file, const PlyDataTypes type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PlyData load_ply_binary(std::ifstream &file, const PlyHeader *header)
|
PlyData load_ply_binary(fstream &file, const PlyHeader *header)
|
||||||
{
|
{
|
||||||
PlyData data;
|
PlyData data;
|
||||||
bool isBigEndian = header->type == PlyFormatType::BINARY_BE;
|
bool isBigEndian = header->type == PlyFormatType::BINARY_BE;
|
||||||
@ -141,7 +140,7 @@ PlyData load_ply_binary(std::ifstream &file, const PlyHeader *header)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_vertex_data(std::ifstream &file, const PlyHeader *header, PlyData *r_data, int index)
|
void load_vertex_data(fstream &file, const PlyHeader *header, PlyData *r_data, int index)
|
||||||
{
|
{
|
||||||
bool hasNormal = false;
|
bool hasNormal = false;
|
||||||
bool hasColor = false;
|
bool hasColor = false;
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "BLI_endian_switch.h"
|
||||||
|
#include "BLI_fileops.hh"
|
||||||
|
|
||||||
#include "ply_data.hh"
|
#include "ply_data.hh"
|
||||||
|
|
||||||
namespace blender::io::ply {
|
namespace blender::io::ply {
|
||||||
@ -16,7 +19,7 @@ namespace blender::io::ply {
|
|||||||
* \param header: The information in the PLY header.
|
* \param header: The information in the PLY header.
|
||||||
* \return The PlyData datastructure that can be used for conversion to a Mesh.
|
* \return The PlyData datastructure that can be used for conversion to a Mesh.
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<PlyData> import_ply_binary(std::ifstream &file, const PlyHeader *header);
|
std::unique_ptr<PlyData> import_ply_binary(fstream &file, const PlyHeader *header);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the information from the PLY file in binary format to the PlyData datastructure.
|
* Loads the information from the PLY file in binary format to the PlyData datastructure.
|
||||||
@ -24,13 +27,13 @@ std::unique_ptr<PlyData> import_ply_binary(std::ifstream &file, const PlyHeader
|
|||||||
* \param header: The information in the PLY header.
|
* \param header: The information in the PLY header.
|
||||||
* \return The PlyData datastructure that can be used for conversion to a Mesh.
|
* \return The PlyData datastructure that can be used for conversion to a Mesh.
|
||||||
*/
|
*/
|
||||||
PlyData load_ply_binary(std::ifstream &file, const PlyHeader *header);
|
PlyData load_ply_binary(fstream &file, const PlyHeader *header);
|
||||||
|
|
||||||
void load_vertex_data(std::ifstream &file, const PlyHeader *header, PlyData *r_data, int index);
|
void load_vertex_data(fstream &file, const PlyHeader *header, PlyData *r_data, int index);
|
||||||
|
|
||||||
void check_file_errors(const std::ifstream &file);
|
void check_file_errors(const fstream &file);
|
||||||
|
|
||||||
void discard_value(std::ifstream &file, const PlyDataTypes type);
|
void discard_value(fstream &file, const PlyDataTypes type);
|
||||||
|
|
||||||
template<typename T> T swap_bytes(T input)
|
template<typename T> T swap_bytes(T input)
|
||||||
{
|
{
|
||||||
@ -42,34 +45,27 @@ template<typename T> T swap_bytes(T input)
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sizeof(T) == 2) {
|
if constexpr (sizeof(T) == 2) {
|
||||||
uint16_t newInput = uint16_t(input);
|
uint16_t value = reinterpret_cast<uint16_t &>(input);
|
||||||
return (T)(((newInput & 0xFF) << 8) | ((newInput >> 8) & 0xFF));
|
BLI_endian_switch_uint16(&value);
|
||||||
|
return reinterpret_cast<T &>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sizeof(T) == 4) {
|
if constexpr (sizeof(T) == 4) {
|
||||||
/* Reinterpret this data as uint32 for easy rearranging of bytes. */
|
/* Reinterpret this data as uint32 for easy rearranging of bytes. */
|
||||||
uint32_t newInput = *(uint32_t *)&input;
|
uint32_t value = reinterpret_cast<uint32_t &>(input);
|
||||||
uint32_t output = 0;
|
BLI_endian_switch_uint32(&value);
|
||||||
for (int i = 0; i < 4; i++) {
|
return reinterpret_cast<T &>(value);
|
||||||
output |= ((newInput >> i * 8) & 0xFF) << (24 - i * 8);
|
|
||||||
}
|
|
||||||
T value = *(T *)&output;
|
|
||||||
return value; /* Reinterpret the bytes of output as a T value. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sizeof(T) == 8) {
|
if constexpr (sizeof(T) == 8) {
|
||||||
/* Reinterpret this data as uint64 for easy rearranging of bytes. */
|
/* Reinterpret this data as uint64 for easy rearranging of bytes. */
|
||||||
uint64_t newInput = *(uint64_t *)&input;
|
uint64_t value = reinterpret_cast<uint64_t &>(input);
|
||||||
uint64_t output = 0;
|
BLI_endian_switch_uint64(&value);
|
||||||
for (int i = 0; i < 8; i++) {
|
return reinterpret_cast<T &>(value);
|
||||||
output |= ((newInput >> i * 8) & 0xFF) << (56 - i * 8);
|
|
||||||
}
|
|
||||||
T value = *(T *)&output;
|
|
||||||
return value; /* Reinterpret the bytes of output as a T value. */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> T read(std::ifstream &file, bool isBigEndian);
|
template<typename T> T read(fstream &file, bool isBigEndian);
|
||||||
|
|
||||||
} // namespace blender::io::ply
|
} // namespace blender::io::ply
|
||||||
|
@ -38,13 +38,13 @@ Mesh *convert_ply_to_mesh(PlyData &data, Mesh *mesh, const PLYImportParams ¶
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add faces and edges to the mesh. */
|
/* Add faces to the mesh. */
|
||||||
if (!data.faces.is_empty()) {
|
if (!data.faces.is_empty()) {
|
||||||
/* Specify amount of total faces. */
|
/* Specify amount of total faces. */
|
||||||
mesh->totpoly = int(data.faces.size());
|
mesh->totpoly = int(data.faces.size());
|
||||||
mesh->totloop = 0;
|
mesh->totloop = 0;
|
||||||
for (int i = 0; i < data.faces.size(); i++) {
|
for (int i = 0; i < data.faces.size(); i++) {
|
||||||
/* Add number of edges to the amount of edges. */
|
/* Add number of loops from the vertex indices in the face. */
|
||||||
mesh->totloop += data.faces[i].size();
|
mesh->totloop += data.faces[i].size();
|
||||||
}
|
}
|
||||||
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, mesh->totpoly);
|
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, mesh->totpoly);
|
||||||
@ -87,7 +87,7 @@ Mesh *convert_ply_to_mesh(PlyData &data, Mesh *mesh, const PLYImportParams ¶
|
|||||||
int counter = 0;
|
int counter = 0;
|
||||||
for (int i = 0; i < data.faces.size(); i++) {
|
for (int i = 0; i < data.faces.size(); i++) {
|
||||||
for (int j = 0; j < data.faces[i].size(); j++) {
|
for (int j = 0; j < data.faces[i].size(); j++) {
|
||||||
copy_v2_v2(uv_map.span[counter], data.UV_coordinates[data.faces[i][j]]);
|
uv_map.span[counter] = data.UV_coordinates[data.faces[i][j]];
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ namespace blender::io::ply {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the PlyData datastructure to a mesh.
|
* Converts the PlyData datastructure to a mesh.
|
||||||
* \param data The PLY data.
|
* \param data: The PLY data.
|
||||||
* \return The mesh that can be used inside blender.
|
* \return The mesh that can be used inside blender.
|
||||||
*/
|
*/
|
||||||
Mesh *convert_ply_to_mesh(PlyData &data, Mesh *mesh, const PLYImportParams ¶ms);
|
Mesh *convert_ply_to_mesh(PlyData &data, Mesh *mesh, const PLYImportParams ¶ms);
|
||||||
|
@ -4,13 +4,11 @@
|
|||||||
* \ingroup ply
|
* \ingroup ply
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "ply_functions.hh"
|
#include "ply_functions.hh"
|
||||||
|
|
||||||
namespace blender::io::ply {
|
namespace blender::io::ply {
|
||||||
|
|
||||||
line_ending safe_getline(std::ifstream &file, std::string &line)
|
line_ending safe_getline(fstream &file, std::string &line)
|
||||||
{
|
{
|
||||||
line.clear();
|
line.clear();
|
||||||
std::streambuf *sb = file.rdbuf();
|
std::streambuf *sb = file.rdbuf();
|
||||||
@ -19,7 +17,7 @@ line_ending safe_getline(std::ifstream &file, std::string &line)
|
|||||||
line_ending possible = UNSET;
|
line_ending possible = UNSET;
|
||||||
char c;
|
char c;
|
||||||
while (sb->sgetc() != std::streambuf::traits_type::eof()) {
|
while (sb->sgetc() != std::streambuf::traits_type::eof()) {
|
||||||
c = (char)sb->sgetc();
|
c = char(sb->sgetc());
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '\n':
|
case '\n':
|
||||||
if (possible == UNSET) {
|
if (possible == UNSET) {
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fstream>
|
#include "BLI_fileops.hh"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace blender::io::ply {
|
namespace blender::io::ply {
|
||||||
@ -17,10 +17,10 @@ enum line_ending { CR_LF, LF, CR, LF_CR, UNSET };
|
|||||||
* Reads a line in the ply file in a line-ending safe manner. All different line endings are
|
* Reads a line in the ply file in a line-ending safe manner. All different line endings are
|
||||||
* supported. This also supports a mix of different line endings in the same file. CR (\\r), LF
|
* supported. This also supports a mix of different line endings in the same file. CR (\\r), LF
|
||||||
* (\\n), CR/LF (\\r\\n), LF/CR (\\n\\r).
|
* (\\n), CR/LF (\\r\\n), LF/CR (\\n\\r).
|
||||||
* @param file The file stream.
|
* \param file: The file stream.
|
||||||
* @param line The string you want to read to.
|
* \param line: The string you want to read to.
|
||||||
* @return The line ending enum if you're interested.
|
* \return The line ending enum if you're interested.
|
||||||
*/
|
*/
|
||||||
line_ending safe_getline(std::ifstream &file, std::string &line);
|
line_ending safe_getline(fstream &file, std::string &line);
|
||||||
|
|
||||||
} // namespace blender::io::ply
|
} // namespace blender::io::ply
|
||||||
|
@ -1,23 +1,12 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
#include "testing/testing.h"
|
#include "testing/testing.h"
|
||||||
#include "tests/blendfile_loading_base_test.h"
|
#include "tests/blendfile_loading_base_test.h"
|
||||||
|
|
||||||
#include "BKE_blender_version.h"
|
#include "BKE_blender_version.h"
|
||||||
#include "BKE_curve.h"
|
|
||||||
#include "BKE_main.h"
|
|
||||||
#include "BKE_scene.h"
|
|
||||||
|
|
||||||
#include "BLI_fileops.h"
|
|
||||||
|
|
||||||
#include "BLO_readfile.h"
|
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
#include "DEG_depsgraph.h"
|
||||||
|
|
||||||
#include "DNA_curve_types.h"
|
|
||||||
#include "DNA_material_types.h"
|
|
||||||
#include "DNA_scene_types.h"
|
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
|
||||||
|
|
||||||
#include "IO_ply.h"
|
#include "IO_ply.h"
|
||||||
#include "intern/ply_data.hh"
|
#include "intern/ply_data.hh"
|
||||||
|
|
||||||
@ -463,7 +452,7 @@ TEST_F(ply_exporter_ply_data_test, SuzanneLoadPLYDataUV)
|
|||||||
params.export_uv = true;
|
params.export_uv = true;
|
||||||
PlyData plyData = load_ply_data_from_blendfile("io_tests/blend_geometry/suzanne_all_data.blend",
|
PlyData plyData = load_ply_data_from_blendfile("io_tests/blend_geometry/suzanne_all_data.blend",
|
||||||
params);
|
params);
|
||||||
EXPECT_EQ(plyData.UV_coordinates.size(), 541);
|
EXPECT_EQ(plyData.UV_coordinates.size(), 542);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ply_exporter_ply_data_test, CubeLoadPLYDataUVDisabled)
|
TEST_F(ply_exporter_ply_data_test, CubeLoadPLYDataUVDisabled)
|
||||||
|
@ -1,28 +1,15 @@
|
|||||||
#include "testing/testing.h"
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
#include "tests/blendfile_loading_base_test.h"
|
#include "tests/blendfile_loading_base_test.h"
|
||||||
|
|
||||||
#include "BKE_attribute.hh"
|
#include "BKE_attribute.hh"
|
||||||
#include "BKE_curve.h"
|
|
||||||
#include "BKE_main.h"
|
|
||||||
#include "BKE_mesh.h"
|
#include "BKE_mesh.h"
|
||||||
#include "BKE_object.h"
|
#include "BKE_object.h"
|
||||||
#include "BKE_scene.h"
|
|
||||||
|
|
||||||
#include "BLI_math_vector_types.hh"
|
|
||||||
|
|
||||||
#include "BLO_readfile.h"
|
#include "BLO_readfile.h"
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
|
||||||
#include "DEG_depsgraph_query.h"
|
#include "DEG_depsgraph_query.h"
|
||||||
|
|
||||||
#include "DNA_curve_types.h"
|
|
||||||
#include "DNA_material_types.h"
|
|
||||||
#include "DNA_mesh_types.h"
|
|
||||||
#include "DNA_meshdata_types.h"
|
|
||||||
#include "DNA_scene_types.h"
|
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
|
||||||
|
|
||||||
#include "IO_ply.h"
|
#include "IO_ply.h"
|
||||||
#include "ply_data.hh"
|
#include "ply_data.hh"
|
||||||
#include "ply_import.hh"
|
#include "ply_import.hh"
|
||||||
|
Loading…
Reference in New Issue
Block a user