Commit 3c84e16c authored by Martin Heistermann's avatar Martin Heistermann
Browse files

wip

parent b0e72f11
Pipeline #19019 failed with stage
in 2 minutes and 33 seconds
meta:
id: ovmb
title: OVMB (OpenVolumeMesh binary file format)
file-extension:
- ovmb
license: CC0-1.0
encoding: ASCII
endian: le
doc:
OVMB files describe volumetric meshes and associated properties.
doc-ref: http://openvolumemesh.org
seq:
- id: file_header
type: file_header
- id: chunks
type: chunk
repeat: eos
enums:
int_encoding:
0: none
1: u8
2: u16
4: u32
vertex_encoding:
0: none
1: float
2: double
property_entity:
0: vertex
1: edge
2: face
3: cell
4: halfedge
5: halfface
6: mesh
topo_type:
0: polyhedral
1: tetrahedral
2: hexahedral
types:
file_header:
seq:
- id: magic
contents: ['O', 'V', 'M', 'B', '\n', '\r', '\n', 0xff]
- id: file_version
type: u1
- id: header_version
type: u1
- id: vertex_dim
type: u1
- id: vertex_encoding
type: u1
enum: vertex_encoding
- id: topo_type
type: u1
enum: topo_type
- id: n_vertices
type: u8
- id: n_edges
type: u8
- id: n_faces
type: u8
- id: n_cells
type: u8
chunk:
seq:
- id: type
type: str
size: 4
- id: version
type: u1
- id: padding_bytes
type: u1
- id: compression
type: u1
- id: flags
type: u1
- id: file_length
type: u8
- id: body
size: file_length
type:
switch-on: type
cases:
'"VERT"': vert_chunk
'"PROP"': prop_chunk
'"EDGE"': topo_chunk
'"FACE"': topo_chunk
'"CELL"': topo_chunk
array_span:
seq:
- id: base
type: u8
- id: count
type: u4
vert_chunk:
seq:
- id: span
type: array_span
- id: vertex_encoding
type: u1
enum: vertex_encoding
- id: positions
repeat: expr
repeat-expr: span.count
type:
switch-on: vertex_encoding
cases:
'vertex_encoding::float': f4
'vertex_encoding::double': f8
topo_chunk:
seq:
- id: span
type: array_span
- id: int_encoding
type: u1
enum: int_encoding
- id: valence
type: u1
doc: 0 for variable valence
- id: valence_encoding
type: u1
enum: int_encoding
- id: reserved
size: 1
- id: handle_offset
type: u8
- id: data
type:
switch-on: valence
cases:
0: topo_data_variable
_: topo_data_fixed
topo_data_fixed:
seq:
- id: handles
repeat: expr
repeat-expr: _parent.span.count * _parent.valence
type:
switch-on: _parent.int_encoding
cases:
'int_encoding::u8': u1
'int_encoding::u16': u2
'int_encoding::u32': u4
topo_data_variable:
seq:
- id: valences
repeat: expr
repeat-expr: _parent.span.count
type:
switch-on: _parent.valence_encoding
cases:
'int_encoding::u8': u1
'int_encoding::u16': u2
'int_encoding::u32': u4
- id: handles
repeat: eos
type:
switch-on: _parent.int_encoding
cases:
'int_encoding::u8': u1
'int_encoding::u16': u2
'int_encoding::u32': u4
prop_chunk:
seq:
- id: span
type: array_span
- id: prop_idx
type: u4
propdir_chunk:
seq:
- id: entry
type: propdir_entry
repeat: eos
string4:
seq:
- id: len
type: u4
- id: data
size: len
propdir_entry:
seq:
- id: entity
type: u1
enum: property_entity
- id: name
type: string4
- id: data_type_name
type: string4
- id: serialized_default
type: string4
......@@ -54,20 +54,20 @@ void BinaryFileReader::readFacesOrCells(
};
auto esize = elem_size(header.enc);
auto handle_size = elem_size(header.handle_encoding);
if (fixed_valence == 0) {
auto valences = read_valences(reader, valence_enc, header.span.count);
auto max_valence = *std::max_element(valences.begin(), valences.end());
auto total_handles = std::accumulate(valences.begin(), valences.end(), 0ULL);
if (reader.remaining_bytes() != total_handles * esize) {
if (reader.remaining_bytes() != total_handles * handle_size) {
state_ = ReadState::Error;
return;
}
handles.reserve(max_valence);
add_all([&](size_t idx){return valences[idx];});
} else {
if (reader.remaining_bytes() != header.span.count * fixed_valence * esize) {
if (reader.remaining_bytes() != header.span.count * fixed_valence * handle_size) {
state_ = ReadState::Error;
return;
}
......@@ -165,11 +165,21 @@ void BinaryFileReader::readPropChunk(Decoder &reader)
static_cast<size_t>(header.span.base + header.span.count));
}
void BinaryFileReader::readEdgesChunk(Decoder &reader)
void BinaryFileReader::readTopoChunk(Decoder &reader)
{
TopoChunkHeader header;
read(reader, header);
if (!is_valid(header.enc)) {
if (header.entity == TopoEntity::Edge) {
if (header.valence != 2) {
state_ = ReadState::ErrorInvalidFile;
return;
}
if (header.valence_encoding != IntEncoding::None) {
state_ = ReadState::ErrorInvalidFile;
return;
}
}
if (!is_valid(header.handle_encoding)) {
state_ = ReadState::ErrorInvalidEncoding;
return;
}
......@@ -179,7 +189,7 @@ void BinaryFileReader::readEdgesChunk(Decoder &reader)
auto read_all = [&](auto read_one)
{
if (reader.remaining_bytes() != header.span.count * 2 * elem_size(header.enc)) {
if (reader.remaining_bytes() != header.span.count * 2 * elem_size(header.handle_encoding)) {
std::cerr << "edge chunk size " << std::endl;
state_ = ReadState::ErrorInvalidChunkSize;
return;
......@@ -197,7 +207,7 @@ void BinaryFileReader::readEdgesChunk(Decoder &reader)
}
};
call_with_decoder(header.enc, read_all);
call_with_decoder(header.handle_encoding, read_all);
if (state_ == ReadState::ReadingChunks) {
n_edges_read_ += header.span.count;
......@@ -213,7 +223,7 @@ void BinaryFileReader::readFacesChunk(Decoder &reader)
IntEncoding valence_enc; read(reader, valence_enc);
reader.reserved<2>();
if (!is_valid(header.enc)) {
if (!is_valid(header.handle_encoding)) {
state_ = ReadState::ErrorInvalidEncoding;
return;
}
......@@ -238,7 +248,7 @@ void BinaryFileReader::readFacesChunk(Decoder &reader)
read_one, add_face);
};
call_with_decoder(header.enc, read_all);
call_with_decoder(header.handle_encoding, read_all);
if (state_ == ReadState::ReadingChunks) {
n_faces_read_ += header.span.count;
......@@ -254,7 +264,7 @@ void BinaryFileReader::readCellsChunk(Decoder &reader)
IntEncoding valence_enc; read(reader, valence_enc);
reader.reserved<2>();
if (!is_valid(header.enc)) {
if (!is_valid(header.handle_encoding)) {
state_ = ReadState::ErrorInvalidEncoding;
return;
}
......@@ -282,7 +292,7 @@ void BinaryFileReader::readCellsChunk(Decoder &reader)
read_one, add_cell);
};
call_with_decoder(header.enc, read_all);
call_with_decoder(header.handle_encoding, read_all);
if (state_ == ReadState::ReadingChunks) {
n_cells_read_ += header.span.count;
......@@ -296,7 +306,7 @@ readVerticesChunk(Decoder &reader)
VertexChunkHeader header;
read(reader, header);
if (!is_valid(header.enc)) {
if (!is_valid(header.vertex_encoding)) {
state_ = ReadState::ErrorInvalidEncoding;
return;
}
......@@ -437,15 +447,9 @@ read_chunk()
case ChunkType::Vertices:
readVerticesChunk(chunk_reader);
break;
case ChunkType::Edges:
readEdgesChunk(chunk_reader);
break;
case ChunkType::Faces:
readFacesChunk(chunk_reader);
break;
case ChunkType::Cells:
readCellsChunk(chunk_reader);
break;
case ChunkType::Topo:
readTopoChunk(chunk_reader);
break;
default:
if (header.isMandatory()) {
state_ = ReadState::ErrorUnsupportedChunkType;
......
......@@ -46,9 +46,7 @@ private:
void read_chunk();
void readPropDirChunk(Decoder &reader);
void readVerticesChunk(Decoder &reader);
void readEdgesChunk(Decoder &reader);
void readFacesChunk(Decoder &reader);
void readCellsChunk(Decoder &reader);
void readTopoChunk(Decoder &reader);
void readPropChunk(Decoder &reader);
template<typename HandleT, typename ReadFunc, typename AddFunc>
......
......@@ -146,12 +146,10 @@ void BinaryFileWriter::write_vertices(uint32_t first, uint32_t count)
{
if (count == 0) return;
VertexChunkHeader header;
header.span.base = first;
header.span.count = count;
header.enc = VertexEncoding::Double;
header.vertex_encoding = VertexEncoding::Double;
chunk_buffer_.reset();
chunk_buffer_.need(
......@@ -173,14 +171,17 @@ void BinaryFileWriter::write_edges(uint32_t first, uint32_t count)
TopoChunkHeader header;
header.span.base = first;
header.span.count = count;
header.enc = suitable_int_encoding(mesh_.n_vertices());
header.entity = TopoEntity::Edge;
header.handle_encoding = suitable_int_encoding(mesh_.n_vertices());
header.valence = 2;
header.valence_encoding = IntEncoding::None;
header.handle_offset = 0;
chunk_buffer_.reset();
chunk_buffer_.need(
ovmb_size<TopoChunkHeader>
+ count * 2 * elem_size(header.enc));
+ count * 2 * elem_size(header.handle_encoding));
Encoder encoder(chunk_buffer_);
write(encoder, header);
......@@ -196,9 +197,9 @@ void BinaryFileWriter::write_edges(uint32_t first, uint32_t count)
write_one(encoder, mesh_. to_vertex_handle(heh).uidx());
}
};
call_with_encoder(header.enc, write_all);
call_with_encoder(header.handle_encoding, write_all);
write_chunk(ChunkType::Edges);
write_chunk(ChunkType::Topo);
}
void BinaryFileWriter::write_faces(uint32_t first, uint32_t count)
......@@ -211,9 +212,13 @@ void BinaryFileWriter::write_faces(uint32_t first, uint32_t count)
TopoChunkHeader header;
header.span.base = first;
header.span.count = count;
header.enc = suitable_int_encoding(mesh_.n_halfedges());
header.entity = TopoEntity::Face;
header.valence = 2;
header.valence_encoding = IntEncoding::None;
header.handle_encoding = suitable_int_encoding(mesh_.n_halfedges());
header.handle_offset = 0;
write(encoder, header);
std::vector<uint32_t> valences;
......@@ -236,9 +241,9 @@ void BinaryFileWriter::write_faces(uint32_t first, uint32_t count)
}
}
};
call_with_encoder(header.enc, write_all);
call_with_encoder(header.handle_encoding, write_all);
write_chunk(ChunkType::Faces);
write_chunk(ChunkType::Topo);
}
void BinaryFileWriter::write_cells(uint32_t first, uint32_t count)
......@@ -251,7 +256,8 @@ void BinaryFileWriter::write_cells(uint32_t first, uint32_t count)
TopoChunkHeader header;
header.span.base = first;
header.span.count = count;
header.enc = suitable_int_encoding(mesh_.n_halffaces());
header.entity = TopoEntity::Cell;
header.handle_encoding = suitable_int_encoding(mesh_.n_halffaces());
header.handle_offset = 0;
write(encoder, header);
......@@ -277,9 +283,9 @@ void BinaryFileWriter::write_cells(uint32_t first, uint32_t count)
}
}
};
call_with_encoder(header.enc, write_all);
call_with_encoder(header.handle_encoding, write_all);
write_chunk(ChunkType::Cells);
write_chunk(ChunkType::Topo);
}
void BinaryFileWriter::write_propdir()
......
......@@ -135,7 +135,7 @@ void read(Decoder &decoder, PropChunkHeader &_out)
void write(Encoder &encoder, const VertexChunkHeader & val)
{
write(encoder, val.span);
write(encoder, val.enc);
write(encoder, val.vertex_encoding);
encoder.reserved<3>();
}
......@@ -143,15 +143,16 @@ void read(Decoder &decoder, VertexChunkHeader &_out)
{
decoder.need(ovmb_size<VertexChunkHeader>);
read(decoder, _out.span);
read(decoder, _out.enc);
read(decoder, _out.vertex_encoding);
decoder.reserved<3>();
}
void write(Encoder &encoder, const TopoChunkHeader & val)
{
write(encoder, val.span);
write(encoder, val.enc);
encoder.reserved<3>();
encoder.u8(val.valence);
write(encoder, val.valence_encoding);
write(encoder, val.handle_encoding);
encoder.u64(val.handle_offset);
}
......@@ -159,8 +160,10 @@ void read(Decoder &decoder, TopoChunkHeader &_out)
{
decoder.need(ovmb_size<TopoChunkHeader>);
read(decoder, _out.span);
read(decoder, _out.enc);
decoder.reserved<3>();
read(decoder, _out.entity);
_out.valence = decoder.u8();
read(decoder, _out.valence_encoding);
read(decoder, _out.handle_encoding);
_out.handle_offset = decoder.u64();
}
......
......@@ -60,6 +60,19 @@ inline bool is_valid(PropertyEntity ent) {
OVM_EXPORT EntityType as_entity_type(PropertyEntity pe);
OVM_EXPORT PropertyEntity as_prop_entity(EntityType pe);
enum class TopoEntity : uint8_t {
Edge = 1,
Face = 2,
Cell = 3,
};
template<> inline size_t ovmb_size<TopoEntity> = 1;
template<> struct OVM_EXPORT is_ovmb_enum<TopoEntity> : std::true_type {};
inline bool is_valid(TopoEntity ent) {
return static_cast<uint8_t>(ent) >= 0
&& static_cast<uint8_t>(ent) <= 3;
}
enum class TopoType : uint8_t {
Polyhedral = 0,
Tetrahedral = 1,
......@@ -99,7 +112,7 @@ struct FileHeader {
uint8_t file_version;
uint8_t header_version;
uint8_t vertex_dim;
VertexEncoding vertex_encoding;
VertexEncoding vertex_encoding; // TODO: remove this
TopoType topo_type;
// 3 bytes padding
uint64_t n_verts;
......@@ -128,9 +141,7 @@ static constexpr uint32_t fourcc(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
enum class ChunkType : uint32_t{
Any = 0, // not used in files!
Vertices = FOURCC("VERT"),
Edges = FOURCC("EDGE"),
Faces = FOURCC("FACE"),
Cells = FOURCC("CELL"),
Topo = FOURCC("TOPO"),
PropertyDirectory = FOURCC("DIRP"),
Property = FOURCC("PROP"),
EndOfFile = FOURCC("EOF "),
......@@ -260,18 +271,26 @@ template<> inline size_t ovmb_size<PropChunkHeader> = ovmb_size<ArraySpan> + siz
struct VertexChunkHeader {
ArraySpan span;
VertexEncoding enc;
VertexEncoding vertex_encoding;
// 3 bytes padding
};
template<> inline size_t ovmb_size<VertexChunkHeader> = ovmb_size<ArraySpan> + 1 + 3;
struct TopoChunkHeader {
ArraySpan span;
IntEncoding enc;
// 3 bytes padding
TopoEntity entity;
uint8_t valence; // 0 for variable valence
IntEncoding valence_encoding; // 'None' if valence is not variable
IntEncoding handle_encoding;
uint64_t handle_offset; // a value to add to every contained handle, can be used for file compression
};
template<> inline size_t ovmb_size<TopoChunkHeader> = ovmb_size<ArraySpan> + 1 + 3 + sizeof(TopoChunkHeader::handle_offset);
template<> inline size_t ovmb_size<TopoChunkHeader> = (
ovmb_size<ArraySpan> +
ovmb_size<IntEncoding> +
ovmb_size<TopoEntity> +
+ sizeof(TopoChunkHeader::valence) +
ovmb_size<IntEncoding> +
+ sizeof(TopoChunkHeader::handle_offset));
} // namespace OpenVolumeMesh::IO::detail
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment