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);
|
||||
uiLayoutSetPropDecorate(layout, false);
|
||||
|
||||
uiLayout *box, *col, *sub, *row;
|
||||
uiLayout *box, *col, *sub;
|
||||
|
||||
/* Object Transform options. */
|
||||
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, "global_scale", 0, NULL, ICON_NONE);
|
||||
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "forward_axis", 0, IFACE_("Forward Axis"), ICON_NONE);
|
||||
row = uiLayoutRow(box, false);
|
||||
uiItemR(row, imfptr, "up_axis", 0, IFACE_("Up Axis"), ICON_NONE);
|
||||
uiItemR(sub, imfptr, "forward_axis", 0, IFACE_("Forward Axis"), ICON_NONE);
|
||||
uiItemR(sub, imfptr, "up_axis", 0, IFACE_("Up Axis"), ICON_NONE);
|
||||
|
||||
col = uiLayoutColumn(box, false);
|
||||
sub = uiLayoutColumn(col, false);
|
||||
|
@ -23,29 +23,33 @@ set(INC_SYS
|
||||
)
|
||||
|
||||
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_header.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_header.hh
|
||||
exporter/ply_export_load_plydata.hh
|
||||
exporter/ply_export.hh
|
||||
exporter/ply_file_buffer_ascii.hh
|
||||
exporter/ply_file_buffer_binary.hh
|
||||
exporter/ply_export_load_plydata.hh
|
||||
importer/ply_import.hh
|
||||
importer/ply_import_binary.hh
|
||||
exporter/ply_file_buffer.hh
|
||||
importer/ply_import_ascii.hh
|
||||
importer/ply_import_binary.hh
|
||||
importer/ply_import_mesh.hh
|
||||
importer/ply_import.hh
|
||||
IO_ply.h
|
||||
|
||||
intern/ply_data.hh
|
||||
intern/ply_functions.hh
|
||||
|
@ -35,11 +35,9 @@ void exporter_main(Main *bmain,
|
||||
bContext *C,
|
||||
const PLYExportParams &export_params)
|
||||
{
|
||||
/* Load mesh data into PlyData struct. */
|
||||
std::unique_ptr<blender::io::ply::PlyData> plyData = std::make_unique<PlyData>();
|
||||
load_plydata(*plyData, CTX_data_ensure_evaluated_depsgraph(C), export_params);
|
||||
|
||||
/* Get filebuffer. */
|
||||
std::unique_ptr<FileBuffer> buffer;
|
||||
|
||||
if (export_params.ascii_format) {
|
||||
@ -49,19 +47,14 @@ void exporter_main(Main *bmain,
|
||||
buffer = std::make_unique<FileBufferBinary>(export_params.filepath);
|
||||
}
|
||||
|
||||
/* Generate and write header. */
|
||||
write_header(*buffer.get(), *plyData.get(), export_params);
|
||||
|
||||
/* Generate and write vertices. */
|
||||
write_vertices(*buffer.get(), *plyData.get());
|
||||
|
||||
/* Generate and write faces. */
|
||||
write_faces(*buffer.get(), *plyData.get());
|
||||
|
||||
/* Generate and write edges. */
|
||||
write_edges(*buffer.get(), *plyData.get());
|
||||
|
||||
/* Clean up. */
|
||||
buffer->close_file();
|
||||
}
|
||||
} // 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();
|
||||
for (int i = 0; i < vertex_map.size(); i++) {
|
||||
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]]);
|
||||
}
|
||||
}
|
||||
|
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.
|
||||
* All writes are done into an internal chunked memory buffer
|
||||
* (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.
|
||||
*/
|
||||
class FileBuffer : private NonMovable {
|
||||
private:
|
||||
using VectorChar = Vector<char>;
|
||||
Vector<VectorChar> blocks_;
|
||||
size_t buffer_chunk_size_;
|
||||
@ -40,57 +39,14 @@ class FileBuffer : private NonMovable {
|
||||
FILE *outfile_;
|
||||
|
||||
public:
|
||||
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) + ".");
|
||||
}
|
||||
}
|
||||
FileBuffer(const char *filepath, size_t buffer_chunk_size = 64 * 1024);
|
||||
|
||||
virtual ~FileBuffer() = default;
|
||||
|
||||
/* Write contents to the buffer(s) into a file, and clear the buffers. */
|
||||
void write_to_file()
|
||||
{
|
||||
for (const auto &b : blocks_)
|
||||
fwrite(b.data(), 1, b.size(), this->outfile_);
|
||||
blocks_.clear();
|
||||
}
|
||||
void write_to_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();
|
||||
}
|
||||
void close_file();
|
||||
|
||||
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;
|
||||
|
||||
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_element(StringRef name, int count);
|
||||
|
||||
void write_header_list_property(StringRef countType, StringRef dataType, StringRef name)
|
||||
{
|
||||
write_fstring("property list {} {} {}\n", countType, dataType, name);
|
||||
}
|
||||
void write_header_scalar_property(StringRef dataType, StringRef name);
|
||||
|
||||
void write_string(StringRef s)
|
||||
{
|
||||
write_fstring("{}\n", s);
|
||||
}
|
||||
void write_header_list_property(StringRef countType, StringRef dataType, StringRef name);
|
||||
|
||||
void write_newline()
|
||||
{
|
||||
write_fstring("\n");
|
||||
}
|
||||
void write_string(StringRef s);
|
||||
|
||||
void write_newline();
|
||||
|
||||
protected:
|
||||
/* 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. */
|
||||
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_));
|
||||
}
|
||||
}
|
||||
void ensure_space(size_t at_least);
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
void write_bytes(Span<char> bytes)
|
||||
{
|
||||
ensure_space(bytes.size());
|
||||
VectorChar &bb = blocks_.last();
|
||||
bb.insert(bb.end(), bytes.begin(), bytes.end());
|
||||
}
|
||||
void write_bytes(Span<char> bytes);
|
||||
};
|
||||
|
||||
} // 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
|
||||
|
||||
#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"
|
||||
|
||||
/* 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 {
|
||||
class FileBufferAscii : public FileBuffer {
|
||||
public:
|
||||
using FileBuffer::FileBuffer;
|
||||
|
||||
void write_vertex(float x, float y, float z) override
|
||||
{
|
||||
write_fstring("{} {} {}", x, y, z);
|
||||
}
|
||||
public:
|
||||
void write_vertex(float x, float y, float z) override;
|
||||
|
||||
void write_UV(float u, float v) override
|
||||
{
|
||||
write_fstring(" {} {}", u, v);
|
||||
}
|
||||
void write_UV(float u, float v) override;
|
||||
|
||||
void write_vertex_normal(float nx, float ny, float nz) override
|
||||
{
|
||||
write_fstring(" {} {} {}", nx, ny, nz);
|
||||
}
|
||||
void write_vertex_normal(float nx, float ny, float nz) override;
|
||||
|
||||
void write_vertex_color(uchar r, uchar g, uchar b, uchar a) override
|
||||
{
|
||||
write_fstring(" {} {} {} {}", r, g, b, a);
|
||||
}
|
||||
void write_vertex_color(uchar r, uchar g, uchar b, uchar a) override;
|
||||
|
||||
void write_vertex_end() override
|
||||
{
|
||||
write_fstring("\n");
|
||||
}
|
||||
void write_vertex_end() override;
|
||||
|
||||
void write_face(char count, Array<uint32_t> const &vertex_indices) override
|
||||
{
|
||||
write_fstring("{}", int(count));
|
||||
void write_face(char count, Array<uint32_t> const &vertex_indices) override;
|
||||
|
||||
for (auto &&v : vertex_indices) {
|
||||
write_fstring(" {}", v);
|
||||
}
|
||||
write_newline();
|
||||
}
|
||||
void write_edge(int first, int second) override
|
||||
{
|
||||
write_fstring("{} {}", first, second);
|
||||
write_newline();
|
||||
}
|
||||
void write_edge(int first, int second) override;
|
||||
};
|
||||
} // 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"
|
||||
|
||||
/* SEP macro from BLI path utils clashes with SEP symbol in fmt headers. */
|
||||
#undef SEP
|
||||
#define FMT_HEADER_ONLY
|
||||
#include <bitset>
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace blender::io::ply {
|
||||
class FileBufferBinary : public FileBuffer {
|
||||
public:
|
||||
using FileBuffer::FileBuffer;
|
||||
|
||||
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));
|
||||
public:
|
||||
void write_vertex(float x, float y, float z) override;
|
||||
|
||||
write_bytes(span);
|
||||
}
|
||||
void write_UV(float u, float v) override;
|
||||
|
||||
void write_UV(float u, float v) override
|
||||
{
|
||||
float2 vector(u, v);
|
||||
char *bits = reinterpret_cast<char *>(&vector);
|
||||
Span<char> span(bits, sizeof(float2));
|
||||
void write_vertex_normal(float nx, float ny, float nz) override;
|
||||
|
||||
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
|
||||
{
|
||||
float3 vector(nx, ny, nz);
|
||||
char *bits = reinterpret_cast<char *>(&vector);
|
||||
Span<char> span(bits, sizeof(float3));
|
||||
void write_vertex_end() override;
|
||||
|
||||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
void write_edge(int first, int second) override;
|
||||
};
|
||||
} // namespace blender::io::ply
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_fileops.hh"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_memory_utils.hh"
|
||||
|
||||
@ -86,11 +87,11 @@ void importer_main(Main *bmain,
|
||||
{
|
||||
|
||||
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;
|
||||
|
||||
while (true) { // We break when end_header is encountered.
|
||||
while (true) { /* We break when end_header is encountered. */
|
||||
safe_getline(infile, line);
|
||||
if (header.header_size == 0 && line != "ply") {
|
||||
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() ||
|
||||
infile.eof()) {
|
||||
/* 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");
|
||||
return;
|
||||
}
|
||||
|
@ -12,14 +12,13 @@
|
||||
|
||||
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>();
|
||||
*data = load_ply_ascii(file, header);
|
||||
std::unique_ptr<PlyData> data = std::make_unique<PlyData>(load_ply_ascii(file, header));
|
||||
return data;
|
||||
}
|
||||
|
||||
PlyData load_ply_ascii(std::ifstream &file, const PlyHeader *header)
|
||||
PlyData load_ply_ascii(fstream &file, const PlyHeader *header)
|
||||
{
|
||||
PlyData data;
|
||||
/* Check if header contains alpha. */
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_fileops.hh"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
|
||||
#include "IO_ply.h"
|
||||
@ -18,7 +20,7 @@ namespace blender::io::ply {
|
||||
* \param file: The PLY file that was opened.
|
||||
* \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.
|
||||
@ -26,7 +28,7 @@ std::unique_ptr<PlyData> import_ply_ascii(std::ifstream &file, PlyHeader *header
|
||||
* \param header: The information in the PLY header.
|
||||
* \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_color_index(const PlyHeader *header);
|
||||
|
@ -10,14 +10,13 @@
|
||||
#include <fstream>
|
||||
|
||||
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>();
|
||||
*data = load_ply_binary(file, header);
|
||||
std::unique_ptr<PlyData> data = std::make_unique<PlyData>(load_ply_binary(file, header));
|
||||
return data;
|
||||
}
|
||||
|
||||
template<typename T> T read(std::ifstream &file, bool isBigEndian)
|
||||
template<typename T> T read(fstream &file, bool isBigEndian)
|
||||
{
|
||||
T returnVal;
|
||||
file.read((char *)&returnVal, sizeof(returnVal));
|
||||
@ -28,16 +27,16 @@ template<typename T> T read(std::ifstream &file, bool isBigEndian)
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
template uint8_t read<uint8_t>(std::ifstream &file, bool isBigEndian);
|
||||
template int8_t read<int8_t>(std::ifstream &file, bool isBigEndian);
|
||||
template uint16_t read<uint16_t>(std::ifstream &file, bool isBigEndian);
|
||||
template int16_t read<int16_t>(std::ifstream &file, bool isBigEndian);
|
||||
template uint32_t read<uint32_t>(std::ifstream &file, bool isBigEndian);
|
||||
template int32_t read<int32_t>(std::ifstream &file, bool isBigEndian);
|
||||
template float read<float>(std::ifstream &file, bool isBigEndian);
|
||||
template double read<double>(std::ifstream &file, bool isBigEndian);
|
||||
template uint8_t read<uint8_t>(fstream &file, bool isBigEndian);
|
||||
template int8_t read<int8_t>(fstream &file, bool isBigEndian);
|
||||
template uint16_t read<uint16_t>(fstream &file, bool isBigEndian);
|
||||
template int16_t read<int16_t>(fstream &file, bool isBigEndian);
|
||||
template uint32_t read<uint32_t>(fstream &file, bool isBigEndian);
|
||||
template int32_t read<int32_t>(fstream &file, bool isBigEndian);
|
||||
template float read<float>(fstream &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()) {
|
||||
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) {
|
||||
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;
|
||||
bool isBigEndian = header->type == PlyFormatType::BINARY_BE;
|
||||
@ -141,7 +140,7 @@ PlyData load_ply_binary(std::ifstream &file, const PlyHeader *header)
|
||||
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 hasColor = false;
|
||||
|
@ -6,6 +6,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_endian_switch.h"
|
||||
#include "BLI_fileops.hh"
|
||||
|
||||
#include "ply_data.hh"
|
||||
|
||||
namespace blender::io::ply {
|
||||
@ -16,7 +19,7 @@ namespace blender::io::ply {
|
||||
* \param header: The information in the PLY header.
|
||||
* \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.
|
||||
@ -24,13 +27,13 @@ std::unique_ptr<PlyData> import_ply_binary(std::ifstream &file, const PlyHeader
|
||||
* \param header: The information in the PLY header.
|
||||
* \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)
|
||||
{
|
||||
@ -42,34 +45,27 @@ template<typename T> T swap_bytes(T input)
|
||||
return input;
|
||||
}
|
||||
|
||||
if (sizeof(T) == 2) {
|
||||
uint16_t newInput = uint16_t(input);
|
||||
return (T)(((newInput & 0xFF) << 8) | ((newInput >> 8) & 0xFF));
|
||||
if constexpr (sizeof(T) == 2) {
|
||||
uint16_t value = reinterpret_cast<uint16_t &>(input);
|
||||
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. */
|
||||
uint32_t newInput = *(uint32_t *)&input;
|
||||
uint32_t output = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
output |= ((newInput >> i * 8) & 0xFF) << (24 - i * 8);
|
||||
}
|
||||
T value = *(T *)&output;
|
||||
return value; /* Reinterpret the bytes of output as a T value. */
|
||||
uint32_t value = reinterpret_cast<uint32_t &>(input);
|
||||
BLI_endian_switch_uint32(&value);
|
||||
return reinterpret_cast<T &>(value);
|
||||
}
|
||||
|
||||
if (sizeof(T) == 8) {
|
||||
if constexpr (sizeof(T) == 8) {
|
||||
/* Reinterpret this data as uint64 for easy rearranging of bytes. */
|
||||
uint64_t newInput = *(uint64_t *)&input;
|
||||
uint64_t output = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
output |= ((newInput >> i * 8) & 0xFF) << (56 - i * 8);
|
||||
}
|
||||
T value = *(T *)&output;
|
||||
return value; /* Reinterpret the bytes of output as a T value. */
|
||||
uint64_t value = reinterpret_cast<uint64_t &>(input);
|
||||
BLI_endian_switch_uint64(&value);
|
||||
return reinterpret_cast<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
|
||||
|
@ -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()) {
|
||||
/* Specify amount of total faces. */
|
||||
mesh->totpoly = int(data.faces.size());
|
||||
mesh->totloop = 0;
|
||||
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();
|
||||
}
|
||||
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;
|
||||
for (int i = 0; i < data.faces.size(); i++) {
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ namespace blender::io::ply {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
Mesh *convert_ply_to_mesh(PlyData &data, Mesh *mesh, const PLYImportParams ¶ms);
|
||||
|
@ -4,13 +4,11 @@
|
||||
* \ingroup ply
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "ply_functions.hh"
|
||||
|
||||
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();
|
||||
std::streambuf *sb = file.rdbuf();
|
||||
@ -19,7 +17,7 @@ line_ending safe_getline(std::ifstream &file, std::string &line)
|
||||
line_ending possible = UNSET;
|
||||
char c;
|
||||
while (sb->sgetc() != std::streambuf::traits_type::eof()) {
|
||||
c = (char)sb->sgetc();
|
||||
c = char(sb->sgetc());
|
||||
switch (c) {
|
||||
case '\n':
|
||||
if (possible == UNSET) {
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include "BLI_fileops.hh"
|
||||
#include <string>
|
||||
|
||||
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
|
||||
* 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).
|
||||
* @param file The file stream.
|
||||
* @param line The string you want to read to.
|
||||
* @return The line ending enum if you're interested.
|
||||
* \param file: The file stream.
|
||||
* \param line: The string you want to read to.
|
||||
* \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
|
||||
|
@ -1,23 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "testing/testing.h"
|
||||
#include "tests/blendfile_loading_base_test.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 "DNA_curve_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "IO_ply.h"
|
||||
#include "intern/ply_data.hh"
|
||||
|
||||
@ -463,7 +452,7 @@ TEST_F(ply_exporter_ply_data_test, SuzanneLoadPLYDataUV)
|
||||
params.export_uv = true;
|
||||
PlyData plyData = load_ply_data_from_blendfile("io_tests/blend_geometry/suzanne_all_data.blend",
|
||||
params);
|
||||
EXPECT_EQ(plyData.UV_coordinates.size(), 541);
|
||||
EXPECT_EQ(plyData.UV_coordinates.size(), 542);
|
||||
}
|
||||
|
||||
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 "BKE_attribute.hh"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
#include "BLO_readfile.h"
|
||||
|
||||
#include "DEG_depsgraph.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 "ply_data.hh"
|
||||
#include "ply_import.hh"
|
||||
|
Loading…
Reference in New Issue
Block a user