summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFrederico Linhares <fred@linhares.blue>2023-06-23 20:45:23 -0300
committerFrederico Linhares <fred@linhares.blue>2023-06-28 10:43:13 -0300
commit8cb751ff015271e1844feece5db2113eaec64af3 (patch)
treecd6c698f46408d3b19d4eaea2547efaf3c651a1a /src
parent66eed8b7548c3e772d3bcb0d351608f0df81ecaf (diff)
feat Create an interface to read binary files
* test/meshes/cube.cgmesh: Store data using Big-Endian order.
Diffstat (limited to 'src')
-rw-r--r--src/binary_reader.cpp90
-rw-r--r--src/binary_reader.hpp54
-rw-r--r--src/vk/mesh.cpp45
-rw-r--r--src/vk/qoi.cpp85
4 files changed, 175 insertions, 99 deletions
diff --git a/src/binary_reader.cpp b/src/binary_reader.cpp
new file mode 100644
index 0000000..5847328
--- /dev/null
+++ b/src/binary_reader.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2022-2023 Frederico de Oliveira Linhares
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "binary_reader.hpp"
+
+#include <fstream>
+
+namespace
+{
+
+union IntAndFloat32bit{
+ uint32_t i;
+ float f;
+};
+
+}
+
+BinaryReader::BinaryReader(std::string file_path):
+ _pointer{0}
+{
+ std::ifstream file(file_path, std::ios::binary | std::ios::ate);
+ if(!file.is_open()) throw std::runtime_error{"failed to open file"};
+
+ this->_size = file.tellg();
+ file.seekg(0);
+ this->data = new uint8_t[this->_size];
+ file.read((char*)data, this->_size);
+}
+
+BinaryReader::BinaryReader(const char *file_path):
+ BinaryReader{std::string(file_path)}
+{
+}
+
+BinaryReader::~BinaryReader()
+{
+ delete[] this->data;
+}
+
+uint8_t
+BinaryReader::read_ui8()
+{
+ return this->data[this->_pointer++];
+}
+
+uint32_t
+BinaryReader::read_ui32()
+{
+ uint8_t b1{this->data[_pointer++]}, b2{this->data[_pointer++]},
+ b3{this->data[_pointer++]}, b4{this->data[_pointer++]};
+
+ return b1 << 24 | b2 << 16 | b3 << 8 | b4;
+}
+
+glm::vec2
+BinaryReader::read_vec2()
+{
+ IntAndFloat32bit x{read_ui32()}, y{read_ui32()};
+
+ return glm::vec2{x.f, y.f};
+}
+
+glm::vec3
+BinaryReader::read_vec3()
+{
+ IntAndFloat32bit x{read_ui32()}, y{read_ui32()}, z{read_ui32()};
+
+ return glm::vec3{x.f, y.f, z.f};
+}
+
+void
+BinaryReader::read_chars(char *str, int size)
+{
+ for(int i{0}; i < size; i++)
+ str[i] = (char)data[this->_pointer++];
+}
+
diff --git a/src/binary_reader.hpp b/src/binary_reader.hpp
new file mode 100644
index 0000000..b2e4de5
--- /dev/null
+++ b/src/binary_reader.hpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2022-2023 Frederico de Oliveira Linhares
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <string>
+
+#include "vk/core.hpp"
+
+class BinaryReader
+{
+ int _pointer;
+ int _size;
+ uint8_t *data;
+
+public:
+
+ BinaryReader(const std::string file_path);
+ BinaryReader(const char *file_path);
+ ~BinaryReader();
+
+ inline int
+ pointer(){return this->_pointer;};
+
+ inline int
+ size(){return this->_size;};
+
+ uint8_t
+ read_ui8();
+
+ uint32_t
+ read_ui32();
+
+ glm::vec2
+ read_vec2();
+
+ glm::vec3
+ read_vec3();
+
+ void
+ read_chars(char *str, int size);
+};
diff --git a/src/vk/mesh.cpp b/src/vk/mesh.cpp
index 70b9d45..9afeac3 100644
--- a/src/vk/mesh.cpp
+++ b/src/vk/mesh.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Frederico de Oliveira Linhares
+ * Copyright 2022-2023 Frederico de Oliveira Linhares
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,9 +16,7 @@
#include "mesh.hpp"
-#include <array>
-#include <fstream>
-
+#include "../binary_reader.hpp"
#include "../command.hpp"
#include "../core.hpp"
#include "vertex_3d.hpp"
@@ -48,51 +46,26 @@ MeshBuilder::MeshBuilder(VK::Mesh *m, const char *mp):
{
}
-uint32_t read_uint32_from_file(std::ifstream &input_file)
-{
- uint32_t data{};
- input_file.read((char*)&data, sizeof(uint32_t));
- return data;
-}
-
-glm::vec2 read_vec2_from_file(std::ifstream &input_file)
-{
- glm::vec2 data{};
- input_file.read((char*)&data.x, sizeof(glm::vec2::value_type));
- input_file.read((char*)&data.y, sizeof(glm::vec2::value_type));
- return data;
-}
-
-glm::vec3 read_vec3_from_file(std::ifstream &input_file)
-{
- glm::vec3 data{};
- input_file.read((char*)&data.x, sizeof(glm::vec3::value_type));
- input_file.read((char*)&data.y, sizeof(glm::vec3::value_type));
- input_file.read((char*)&data.z, sizeof(glm::vec3::value_type));
- return data;
-}
-
void
load_mesh(void *obj)
{
auto self = static_cast<MeshBuilder*>(obj);
- std::ifstream input_file{self->mesh_path};
- if(!input_file.is_open()) throw CommandError{"Failed to open file."};
+ BinaryReader input{self->mesh_path};
self->mesh->queue_family =
cg_core.vk_device_with_swapchain->get_queue_family_with_graphics();
// Load vertexes.
{
- auto vertex_count{read_uint32_from_file(input_file)};
+ auto vertex_count{input.read_ui32()};
std::vector<VK::Vertex3D> vertexes{vertex_count};
for(auto i{0}; i < vertex_count; i++)
{
- vertexes[i].position = read_vec3_from_file(input_file);
- vertexes[i].normal = read_vec3_from_file(input_file);
- vertexes[i].texture_coord = read_vec2_from_file(input_file);
+ vertexes[i].position = input.read_vec3();
+ vertexes[i].normal = input.read_vec3();
+ vertexes[i].texture_coord = input.read_vec2();
}
void *vertexes_data{vertexes.data()};
@@ -106,11 +79,11 @@ load_mesh(void *obj)
// Load indexes.
{
- self->mesh->index_count = read_uint32_from_file(input_file);
+ self->mesh->index_count = input.read_ui32();
std::vector<uint32_t> indexes(self->mesh->index_count);
for(auto i{0}; i < self->mesh->index_count; i++)
- indexes[i] = read_uint32_from_file(input_file);
+ indexes[i] = input.read_ui32();
void *indexes_data{indexes.data()};
size_t indexes_size{sizeof(indexes[0]) * indexes.size()};
diff --git a/src/vk/qoi.cpp b/src/vk/qoi.cpp
index 8b7ef9e..4e2b2a4 100644
--- a/src/vk/qoi.cpp
+++ b/src/vk/qoi.cpp
@@ -19,6 +19,8 @@
#include <array>
#include <fstream>
+#include "../binary_reader.hpp"
+
namespace
{
@@ -88,26 +90,6 @@ color_hash(const RGBA &colors)
return colors.red*3 + colors.green*5 + colors.blue*7 + colors.alpha*11;
}
-void
-read_chars(uint8_t *data, int &p, char *str, int size)
-{
- for(int i{0}; i < size; i++) str[i] = (char)data[p++];
-}
-
-void
-read_ui8(uint8_t *data, int &p, uint8_t &num)
-{
- num = data[p++];
-}
-
-void
-read_ui32(uint8_t *data, int &p, uint32_t &num)
-{
- uint8_t b1{data[p++]}, b2{data[p++]}, b3{data[p++]}, b4{data[p++]};
-
- num = b1 << 24 | b2 << 16 | b3 << 8 | b4;
-}
-
}
namespace VK::QOI
@@ -116,38 +98,22 @@ namespace VK::QOI
Image::Image(const char *file_path, uint8_t channels):
channels{channels}
{
- int data_p{0};
- int data_size;
- uint8_t *data;
-
if(this->channels != 0 && this->channels != 3 && this->channels != 4)
{
throw std::invalid_argument{"invalid number of channels"};
}
- { // Read data from file.
- std::ifstream file(file_path, std::ios::binary | std::ios::ate);
- if(!file)
- {
- throw std::runtime_error{"failed to open QOI file"};
- }
-
- data_size = file.tellg();
- if(data_size < HEADER_SIZE + (int)sizeof(PADDING))
- {
- throw std::runtime_error{"invalid QOI file"};
- }
-
- file.seekg(0);
- data = new uint8_t[data_size];
- file.read((char*)data, data_size);
+ BinaryReader input{file_path};
+ if(input.size() < HEADER_SIZE + (int)sizeof(PADDING))
+ {
+ throw std::runtime_error{"invalid QOI file"};
}
- read_chars(data, data_p, this->header.magic, 4);
- read_ui32(data, data_p, this->header.width);
- read_ui32(data, data_p, this->header.height);
- read_ui8(data, data_p, this->header.channels);
- read_ui8(data, data_p, this->header.colorspace);
+ input.read_chars(this->header.magic, 4);
+ this->header.width = input.read_ui32();
+ this->header.height = input.read_ui32();
+ this->header.channels = input.read_ui8();
+ this->header.colorspace = input.read_ui8();
if(this->header.width == 0 || this->header.height == 0 ||
this->header.channels < 3 || this->header.channels > 4 ||
@@ -165,7 +131,7 @@ Image::Image(const char *file_path, uint8_t channels):
std::array<Pixel, 64> index;
Pixel pixel{};
- int chunks_len = data_size - (int)sizeof(PADDING);
+ int chunks_len = input.size() - (int)sizeof(PADDING);
/*
This algorithm is based on the original implementation that is in GitHub:
@@ -181,25 +147,22 @@ Image::Image(const char *file_path, uint8_t channels):
{
run--;
}
- else if(data_p < chunks_len)
+ else if(input.pointer() < chunks_len)
{
- uint8_t output;
- int b1;
- read_ui8(data, data_p, output);
- b1 = output;
+ int b1 = input.read_ui8();
if (b1 == OP_RGB)
{
- read_ui8(data, data_p, pixel.colors.red);
- read_ui8(data, data_p, pixel.colors.green);
- read_ui8(data, data_p, pixel.colors.blue);
+ pixel.colors.red = input.read_ui8();
+ pixel.colors.green = input.read_ui8();
+ pixel.colors.blue = input.read_ui8();
}
else if (b1 == OP_RGBA)
{
- read_ui8(data, data_p, pixel.colors.red);
- read_ui8(data, data_p, pixel.colors.green);
- read_ui8(data, data_p, pixel.colors.blue);
- read_ui8(data, data_p, pixel.colors.alpha);
+ pixel.colors.red = input.read_ui8();
+ pixel.colors.green = input.read_ui8();
+ pixel.colors.blue = input.read_ui8();
+ pixel.colors.alpha = input.read_ui8();
}
else if ((b1 & MASK_2_BITS) == OP_INDEX)
{
@@ -213,9 +176,7 @@ Image::Image(const char *file_path, uint8_t channels):
}
else if ((b1 & MASK_2_BITS) == OP_LUMA)
{
- int b2;
- read_ui8(data, data_p, output);
- b2 = output;
+ int b2 = input.read_ui8();
int vg = (b1 & 0x3f) - 32;
pixel.colors.red += vg - 8 + ((b2 >> 4) & 0x0f);
pixel.colors.green += vg;
@@ -234,8 +195,6 @@ Image::Image(const char *file_path, uint8_t channels):
this->pixels[pixel_p++] = pixel.colors.blue;
if(this->channels == 4) this->pixels[pixel_p++] = pixel.colors.alpha;
}
-
- delete[] data;
}
Image::~Image()