Jackalope / jrf (public) (License: GPLv3 or later version) (since 2019-11-21) (hash sha1)
Libriary for reading and writing resource files: vertices, indices, meshes, images, models and scene data.
Supports reading from filesystem as well as from zip files.
It uses unique binary container format for those resources.
It is used in tool for converting popular formats like wavefront .obj file, TARGA image to this container and also used in resource loader as part of graphics framework.

It requires jlib libriary (see my user repositories) and libzip.
It is possible to remove libzip dependency.
List of commits:
Subject Hash Author Date (UTC)
Moved read,write functions to read.h,write.h, merged vertices,indices and mesh files to mesh.h 365bcb01b01e95448e223de82e9f9e96b51fa789 Jackalope 2020-05-24 13:21:23
Update for new JLIB target a1152ffa6340863fbbd216a4d38806e2d31d3dd5 Jackalope 2020-05-23 23:27:05
added CMake project PARENT_SCOPE variables JRF_* 5ac8009d6709f681fbe0d59dba8cdd646a3cdc47 Jackalope 2020-05-20 19:06:51
added version number definitions, changed magic number (because incompatible) 46ccce5359274d660b327c667903b9534dc3bfe0 Jackalope 2020-05-19 17:39:57
Changed image formats, BGR->RGB convertion while reading from TARGA 297dd913b6084e890e5bd3d53f88d06a8f14657a Jackalope 2020-05-19 17:17:53
Changed cmake library interface 9c704c515769a03e5b1f82dcb1fd947884f1bd1e Jackalope 2020-05-12 06:58:47
added copyright notice to convert.cpp and convert.h a778f4f4a4783656fefac85440e135ddcda3788c Jackalope 2020-05-12 05:18:35
fixes after prev commit changes fc46b4bacf1c69f6eae0c679b26e3b88d1796217 Jackalope 2020-05-11 08:14:50
convert image from tga and add alpha channel functions 4541972149b6b19afda05c608d4abe88a72098bb Jackalope 2020-05-11 07:49:43
more image formats 77bf7ec016cfb604e4a8e06734a4eb71bb299df0 Jackalope 2020-05-11 07:48:46
added license d7c63a0b6199c7f5c1680559953eef1699ec9a48 Jackalope 2020-05-10 01:01:00
refactoring 66f541c32f51d6ed6f90fba1f3b58561726e8659 Jackalope 2020-05-10 00:55:34
extra vertices check c3bd2141d2eaeb96beb5c8ad29e3333c015db4c8 jp.larry 2019-12-26 14:38:29
removed dead code f4ddde689122f1b96fda5292e69f612bf2ca327d jp.larry 2019-12-26 14:38:06
removed forgotten vertex data_size writing 25244188b395b6cca35502f4156d3e78cc1e74ec jp.larry 2019-12-26 13:19:31
better read errors d6d7bc5df695d694ea0dee225905212ef1dfe41b jp.larry 2019-12-26 13:18:55
changed vertices file structure to prevent undefined behaviour 603e283ccf234f87f6e8c38a669280be36a5aafb jp.larry 2019-12-26 12:35:05
vertex attributes is separated, not inteleaved now d3e7b79c74e9fae7b8b788d1a55db2e664feb107 jp.larry 2019-12-26 01:19:17
compiled on windows with mingw 51eacaf02dd542415cea1edd615d88234fb5b344 Jackalope 2019-12-15 07:05:58
added mesh to read and write functions 173144a8516441420feb4327a66d26fa3f57376d Your Name 2019-12-07 22:09:04
Commit 365bcb01b01e95448e223de82e9f9e96b51fa789 - Moved read,write functions to read.h,write.h, merged vertices,indices and mesh files to mesh.h
Author: Jackalope
Author date (UTC): 2020-05-24 13:21
Committer name: Jackalope
Committer date (UTC): 2020-05-24 13:21
Parent(s): a1152ffa6340863fbbd216a4d38806e2d31d3dd5
Signing key:
Tree: c3c8b3aaa14dc4833a514e2f64b59ec130334b92
File Lines added Lines deleted
include/jrf/convert.h 1 0
include/jrf/image.h 1 34
include/jrf/indices.h 0 66
include/jrf/jrf.h 1 1
include/jrf/mesh.h 57 80
include/jrf/model.h 1 20
include/jrf/read.h 176 7
include/jrf/scene.h 28 98
include/jrf/vertices.h 0 96
include/jrf/write.h 99 1
File include/jrf/convert.h changed (mode: 100644) (index 9cffe4e..e6b5751)
18 18 */ */
19 19 #pragma once #pragma once
20 20 #include "image.h" #include "image.h"
21 #include "result.h"
21 22 #include <jlib/rarray.h> #include <jlib/rarray.h>
22 23
23 24 namespace jrf::convert { namespace jrf::convert {
File include/jrf/image.h changed (mode: 100644) (index 8af9e6d..f334468)
17 17 * along with this library. If not, see <https://www.gnu.org/licenses/> * along with this library. If not, see <https://www.gnu.org/licenses/>
18 18 */ */
19 19 #pragma once #pragma once
20 #include <jlib/io_agent.h>
21 20 #include <jlib/allocate.h> #include <jlib/allocate.h>
22 #include "result.h"
21 #include <cinttypes>
23 22
24 23 namespace jrf { struct Image; } namespace jrf { struct Image; }
25 24 struct jrf::Image struct jrf::Image
 
... ... struct jrf::Image
40 39 [[nodiscard]] uint64_t size() { [[nodiscard]] uint64_t size() {
41 40 return pixel_count() * pixelSize; return pixel_count() * pixelSize;
42 41 } }
43 [[nodiscard]] bool sameUV(const Extent& other) {
44 return width == other.width && height == other.height;
45 }
46 42 uint16_t width; uint16_t width;
47 43 uint16_t height; uint16_t height;
48 44 uint16_t depth; uint16_t depth;
 
... ... struct jrf::Image
57 53 void destroy() { void destroy() {
58 54 jl::deallocate(&p_pixels); jl::deallocate(&p_pixels);
59 55 } }
60 template<typename IO = jl::io_agent> [[nodiscard]]
61 Result read(IO *p_mediator) {
62 if (p_mediator->read(&extent, sizeof(extent)) != sizeof(extent))
63 return Result::MEDIATOR_ERROR;
64 if (p_mediator->read(&format, sizeof(format)) != sizeof(format))
65 return Result::MEDIATOR_ERROR;
66 size = extent.size();
67 if (size == 0) {
68 p_pixels = nullptr;
69 return Result::FILE_NO_DATA;
70 }
71 if (not jl::allocate_bytes(&p_pixels, size))
72 return Result::ALLOCATION_FAIL;
73 if (p_mediator->read(p_pixels, size) != int64_t(size)) {
74 destroy();
75 return Result::MEDIATOR_ERROR;
76 }
77 return Result::SUCCESS;
78 }
79 template<typename IO = jl::io_agent> [[nodiscard]]
80 Result write(IO *p_mediator) const {
81 if (p_mediator->write(&extent, sizeof(extent)) != sizeof(extent))
82 return Result::MEDIATOR_ERROR;
83 if (p_mediator->write(&format, sizeof(format)) != sizeof(format))
84 return Result::MEDIATOR_ERROR;
85 if (p_mediator->write(p_pixels, size) != int64_t(size))
86 return Result::MEDIATOR_ERROR;
87 return Result::SUCCESS;
88 }
89 56 uint8_t *p_pixels; uint8_t *p_pixels;
90 57 uint64_t size; uint64_t size;
91 58 Extent extent; Extent extent;
File include/jrf/indices.h deleted (index 34d7451..0000000)
1 /**
2 * Copyright 2020 Damir Valiev
3 *
4 * This file is part of jrf C++ library.
5 *
6 * This library is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this library. If not, see <https://www.gnu.org/licenses/>
18 */
19 #pragma once
20 #include <jlib/io_agent.h>
21 #include <jlib/allocate.h>
22 #include "result.h"
23
24 namespace jrf
25 {
26 enum IndexFormat : uint32_t { U16 = 2, U32 = 4 };
27 struct Indices;
28 }
29 struct jrf::Indices
30 {
31 void destroy() {
32 jl::deallocate(&p_data);
33 }
34 template<typename IO = jl::io_agent> [[nodiscard]]
35 Result read(IO *p_mediator) {
36 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
37 if (not p_io->read_items(&format))
38 return Result::MEDIATOR_ERROR;
39 if (not p_io->read_items(&size))
40 return Result::MEDIATOR_ERROR;
41 if (size == 0)
42 p_data = nullptr;
43 else {
44 if (not jl::allocate_bytes(&p_data, size))
45 return Result::MEDIATOR_ERROR;
46 if (not p_io->read_bytes(p_data, size))
47 return this->destroy(), Result::MEDIATOR_ERROR;
48 }
49 return Result::SUCCESS;
50 }
51 template<typename IO = jl::io_agent> [[nodiscard]]
52 Result write(IO *p_mediator) const {
53 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
54 if (not p_io->write_items(&format))
55 return Result::MEDIATOR_ERROR;
56 if (not p_io->write_items(&size))
57 return Result::MEDIATOR_ERROR;
58 if (not p_io->write_bytes(p_data, size))
59 return Result::MEDIATOR_ERROR;
60
61 return Result::SUCCESS;
62 }
63 uint8_t *p_data;
64 uint64_t size;
65 IndexFormat format;
66 };
File include/jrf/jrf.h changed (mode: 100644) (index c8e255d..dbb4ccf)
... ... namespace jrf
43 43 static const constexpr union { static const constexpr union {
44 44 struct Data { struct Data {
45 45 uint8_t name[4] = {'J','R','F',' '}; uint8_t name[4] = {'J','R','F',' '};
46 uint32_t version = {JRF_VERSION_NUMBER};
46 uint32_t version = {JRF_CONTAINER_VERSION_NUMBER};
47 47 }; };
48 48 uint64_t integer; uint64_t integer;
49 49 } MAGIC {}; } MAGIC {};
File include/jrf/mesh.h changed (mode: 100644) (index 68245c4..ceca7ff)
17 17 * along with this library. If not, see <https://www.gnu.org/licenses/> * along with this library. If not, see <https://www.gnu.org/licenses/>
18 18 */ */
19 19 #pragma once #pragma once
20 #include "vertices.h"
21 #include "indices.h"
20 #include <jlib/allocate.h>
21 #include <jlib/array.h>
22 22 #include <jlib/string.h> #include <jlib/string.h>
23 #include <jlib/darray.h>
23 #include "result.h"
24 24
25 namespace jrf
26 {
27 template<typename IO = jl::io_agent> [[nodiscard]]
28 Result read_str(IO *p_io, jl::string *p_dst) {
29 jl::darray<char> path_tmp;
30 path_tmp.init();
31 char sym;
32 do {
33 if (p_io->read(&sym, 1) != 1)
34 return Result::MEDIATOR_ERROR;
35 if (not path_tmp.insert(sym))
36 return Result::ALLOCATION_FAIL;
37 }
38 while(sym != '\0');
39 *p_dst = {path_tmp.begin(), path_tmp.end()};
40 return Result::SUCCESS;
41 }
25 namespace jrf {
26 struct Vertices;
27 struct Indices;
42 28 template<typename T> template<typename T>
43 29 struct Data; struct Data;
44 30 struct Mesh; struct Mesh;
31
32 namespace VertexFormatT { enum T : uint16_t {
33 F16, F32, F64,
34 I8, I16, I32, I64,
35 U8, U16, U32, U64
36 }; }
37 using VertexFormat = VertexFormatT::T;
38 constexpr static const uint8_t VERTEX_FORMAT_SIZE[] = {
39 2, 4, 8,
40 1, 2, 4, 8,
41 1, 2, 4, 8
42 };
43 enum VertexAttributeType {
44 POSITION, TEX_COORD, NORMAL,
45 RESERVED_BEGIN,
46 RESERVED_COUNT = 16
47 };
48 static_assert (RESERVED_BEGIN < RESERVED_COUNT);
49 constexpr static const uint8_t VERTEX_ATTRIBUTE_COUNT = RESERVED_COUNT;
50
51 struct VertexAttribute {
52 uint32_t offset;
53 uint16_t dimension_count;
54 VertexFormat format;
55 };
56 using VertexAttributes = jl::array<VertexAttribute, VERTEX_ATTRIBUTE_COUNT>;
57
58 namespace IndexFormatT { enum T : uint32_t {
59 U16 = 2,
60 U32 = 4
61 }; }
62 using IndexFormat = IndexFormatT::T;
45 63 } }
64 struct jrf::Vertices {
65 void destroy() {
66 jl::deallocate(&p_data);
67 }
68 VertexAttributes attributes;
69 uint64_t vecs_count;
70 uint64_t data_size;
71 void *p_data;
72 };
73 struct jrf::Indices {
74 void destroy() {
75 jl::deallocate(&p_data);
76 }
77 uint8_t *p_data;
78 uint64_t size;
79 IndexFormat format;
80 };
46 81 template<typename T> template<typename T>
47 struct jrf::Data
48 {
82 struct jrf::Data {
49 83 void destroy() { void destroy() {
50 84 switch(mode) { switch(mode) {
51 85 case ResourceMode::DATA: u.data.destroy(); break; case ResourceMode::DATA: u.data.destroy(); break;
 
... ... struct jrf::Data
53 87 case ResourceMode::NONE: break; case ResourceMode::NONE: break;
54 88 } }
55 89 } }
56 template<typename IO = jl::io_agent> [[nodiscard]]
57 Result read(IO *p_io) {
58 if (p_io->read(&mode, sizeof(mode)) != sizeof(mode))
59 return Result::MEDIATOR_ERROR;
60 switch(mode) {
61 case ResourceMode::NONE: break;
62 case ResourceMode::DATA: {
63 Result res = u.data.read(p_io);
64 if (res != Result::SUCCESS)
65 return res;
66 } break;
67 case ResourceMode::PATH: {
68 auto res = read_str(p_io, &u.path);
69 if (res != Result::SUCCESS)
70 return res;
71 }
72 }
73 return Result::SUCCESS;
74 }
75 template<typename IO = jl::io_agent> [[nodiscard]]
76 Result write(IO *p_io) const {
77 if (p_io->write(&mode, sizeof(mode)) != sizeof(mode))
78 return Result::MEDIATOR_ERROR;
79 switch(mode) {
80 case ResourceMode::DATA: {
81 Result res = u.data.write(p_io);
82 if (res != Result::SUCCESS)
83 return res;
84 } break;
85 case ResourceMode::PATH: {
86 if (p_io->write(u.path.begin(), u.path.size())
87 != int64_t(u.path.size()))
88 return Result::MEDIATOR_ERROR;
89 } break;
90 default: break;
91 }
92 return Result::SUCCESS;
93 }
94 90 union { union {
95 91 T data; T data;
96 92 jl::string path; jl::string path;
97 93 } u; } u;
98 94 ResourceMode mode; ResourceMode mode;
99 95 }; };
100 struct jrf::Mesh
101 {
96 struct jrf::Mesh {
102 97 void destroy() { void destroy() {
103 98 vert.destroy(); vert.destroy();
104 99 ind .destroy(); ind .destroy();
105 100 } }
106 template<typename IO = jl::io_agent> [[nodiscard]]
107 Result read(IO *p_mediator) {
108 Result res;
109 res = vert.read(p_mediator);
110 if (res != Result::SUCCESS)
111 return res;
112 res = ind.read(p_mediator);
113 if (res != Result::SUCCESS)
114 vert.destroy();
115 return res;
116 }
117 template<typename IO = jl::io_agent> [[nodiscard]]
118 Result write(IO *p_mediator) const {
119 Result res = vert.write(p_mediator);
120 if (res != Result::SUCCESS)
121 return res;
122 return ind.write(p_mediator);
123 }
124 101 Data<Vertices> vert; Data<Vertices> vert;
125 102 Data<Indices> ind; Data<Indices> ind;
126 103 }; };
File include/jrf/model.h changed (mode: 100644) (index 9652ad9..fc7ccb4)
21 21 #include "image.h" #include "image.h"
22 22
23 23 namespace jrf { struct Model; } namespace jrf { struct Model; }
24 struct jrf::Model
25 {
24 struct jrf::Model {
26 25 void destroy() { void destroy() {
27 26 mesh.destroy(); mesh.destroy();
28 27 image.destroy(); image.destroy();
29 28 } }
30 template<typename IO = jl::io_agent> [[nodiscard]]
31 Result read(IO *p_mediator) {
32 Result res;
33 res = mesh.read(p_mediator);
34 if (res != Result::SUCCESS)
35 return res;
36 res = image.read(p_mediator);
37 if (res != Result::SUCCESS)
38 mesh.destroy();
39 return res;
40 }
41 template<typename IO = jl::io_agent> [[nodiscard]]
42 Result write(IO *p_io) const {
43 Result res = mesh.write(p_io);
44 if (res != Result::SUCCESS)
45 return res;
46 return image.write(p_io);
47 }
48 29 Data<Mesh> mesh; Data<Mesh> mesh;
49 30 Data<Image> image; Data<Image> image;
50 31 }; };
File include/jrf/read.h changed (mode: 100644) (index 73c6812..ada8262)
19 19 #pragma once #pragma once
20 20 #include "jrf.h" #include "jrf.h"
21 21 #include "zip.h" #include "zip.h"
22 #include <jlib/darray.h>
22 23 #include <jlib/io_agent_mem_ro.h> #include <jlib/io_agent_mem_ro.h>
23 24 #include <jlib/fs.h> #include <jlib/fs.h>
24 25
26 namespace jrf {
27 template<typename IO = jl::io_agent> [[nodiscard]]
28 Result read_str(IO *p_io, jl::string *p_dst) {
29 jl::darray<char> path_tmp;
30 path_tmp.init();
31 char sym;
32 do {
33 if (p_io->read(&sym, 1) != 1)
34 return Result::MEDIATOR_ERROR;
35 if (not path_tmp.insert(sym))
36 return Result::ALLOCATION_FAIL;
37 }
38 while(sym != '\0');
39 *p_dst = {path_tmp.begin(), path_tmp.end()};
40 return Result::SUCCESS;
41 }
42 template<typename T, typename IO = jl::io_agent> [[nodiscard]]
43 Result read(Data<T> *p, IO *p_io) {
44 if (p_io->read(&p->mode, sizeof(p->mode)) != sizeof(p->mode))
45 return Result::MEDIATOR_ERROR;
46 switch(p->mode) {
47 case ResourceMode::NONE: break;
48 case ResourceMode::DATA: {
49 Result res = p->u.data.read(p_io);
50 if (res != Result::SUCCESS)
51 return res;
52 } break;
53 case ResourceMode::PATH: {
54 auto res = read_str(p_io, &p->u.path);
55 if (res != Result::SUCCESS)
56 return res;
57 }
58 }
59 return Result::SUCCESS;
60 }
61 template<typename IO = jl::io_agent> [[nodiscard]]
62 Result read(Vertices *p, IO *p_mediator) {
63 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
64 if (not p_io->read_items(&p->attributes))
65 return Result::MEDIATOR_ERROR;
66 if (not p_io->read_items(&p->vecs_count))
67 return Result::MEDIATOR_ERROR;
68 jl::array<size_t, VERTEX_ATTRIBUTE_COUNT> asizes;
69 p->data_size = 0;
70 for (uint8_t a = 0; a < VERTEX_ATTRIBUTE_COUNT; ++a) {
71 asizes[a] = p->attributes[a].dimension_count
72 * VERTEX_FORMAT_SIZE[p->attributes[a].format] * p->vecs_count;
73 p->data_size += asizes[a];
74 }
75 for (uint8_t a = 0; a < VERTEX_ATTRIBUTE_COUNT; ++a)
76 if (p->attributes[a].offset + asizes[a] > p->data_size)
77 return Result::FILE_CORRUPTED;
78 if (p->data_size == 0)
79 return Result::FILE_NO_DATA;
80 if (not jl::allocate_bytes(&p->p_data, p->data_size))
81 return Result::MEDIATOR_ERROR;
82 if (not p_io->read_bytes(p->p_data, p->data_size)) {
83 p->destroy();
84 return Result::MEDIATOR_ERROR;
85 }
86 return Result::SUCCESS;
87 }
88 template<typename IO = jl::io_agent> [[nodiscard]]
89 Result read(Indices *p, IO *p_mediator) {
90 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
91 if (not p_io->read_items(&p->format))
92 return Result::MEDIATOR_ERROR;
93 if (not p_io->read_items(&p->size))
94 return Result::MEDIATOR_ERROR;
95 if (p->size == 0)
96 p->p_data = nullptr;
97 else {
98 if (not jl::allocate_bytes(&p->p_data, p->size))
99 return Result::MEDIATOR_ERROR;
100 if (not p_io->read_bytes(p->p_data, p->size)) {
101 p->destroy();
102 return Result::MEDIATOR_ERROR;
103 }
104 }
105 return Result::SUCCESS;
106 }
107 template<typename IO = jl::io_agent> [[nodiscard]]
108 Result read(Mesh *p, IO *p_mediator) {
109 Result res;
110 res = read(&p->vert, p_mediator);
111 if (res != Result::SUCCESS)
112 return res;
113 res = read(&p->ind, p_mediator);
114 if (res != Result::SUCCESS)
115 p->vert.destroy();
116 return res;
117 }
118 template<typename IO = jl::io_agent> [[nodiscard]]
119 Result read(Image *p, IO *p_mediator) {
120 if (p_mediator->read(&p->extent, sizeof(p->extent)) != sizeof(p->extent))
121 return Result::MEDIATOR_ERROR;
122 if (p_mediator->read(&p->format, sizeof(p->format)) != sizeof(p->format))
123 return Result::MEDIATOR_ERROR;
124 p->size = p->extent.size();
125 if (p->size == 0) {
126 p->p_pixels = nullptr;
127 return Result::FILE_NO_DATA;
128 }
129 if (not jl::allocate_bytes(&p->p_pixels, p->size))
130 return Result::ALLOCATION_FAIL;
131 if (p_mediator->read(p->p_pixels, p->size) != int64_t(p->size)) {
132 p->destroy();
133 return Result::MEDIATOR_ERROR;
134 }
135 return Result::SUCCESS;
136 }
137 template<typename IO = jl::io_agent> [[nodiscard]]
138 Result read(Model *p, IO *p_mediator) {
139 Result res;
140 res = read(&p->mesh, p_mediator);
141 if (res != Result::SUCCESS)
142 return res;
143 res = read(&p->image, p_mediator);
144 if (res != Result::SUCCESS)
145 p->mesh.destroy();
146 return res;
147 }
148 template<typename IO = jl::io_agent> [[nodiscard]]
149 Result read(SceneEntry *p, IO *p_mediator) {
150 Result res = read_str(p_mediator, &p->model_path);
151 if (res != Result::SUCCESS)
152 return res;
153 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
154 if (not p_io->read_items(&p->options.pos))
155 goto CANCEL;
156 if (not p_io->read_items(&p->options.shift))
157 goto CANCEL;
158 if (not p_io->read_items(&p->options.transform))
159 goto CANCEL;
160 return Result::SUCCESS;
161 CANCEL:
162 p->destroy();
163 return Result::MEDIATOR_ERROR;
164 }
165 template<typename IO = jl::io_agent> [[nodiscard]]
166 Result read(Scene *p, IO *p_mediator) {
167 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
168 if (not p_io->read_items(&p->options.shift))
169 return Result::MEDIATOR_ERROR;
170 if (not p_io->read_items(&p->options.shift_po2))
171 return Result::MEDIATOR_ERROR;
172 uint64_t entry_count;
173 if (not p_io->read_items(&entry_count))
174 return Result::MEDIATOR_ERROR;
175 if (entry_count == 0) {
176 p->entries.init();
177 return Result::SUCCESS;
178 }
179 if (not p->entries.init(entry_count))
180 return Result::ALLOCATION_FAIL;
181 for (uint64_t i = 0; i < entry_count; ++i) {
182 Result res = read(&p->entries[i], p_mediator);
183 if (res != Result::SUCCESS) {
184 while(i > 0)
185 p->entries[--i].destroy();
186 p->entries.destroy();
187 return res;
188 }
189 }
190 return Result::SUCCESS;
191 }
192 }
193
25 194 namespace jrf::details { namespace jrf::details {
26 195 template<typename IO = jl::io_agent> template<typename IO = jl::io_agent>
27 196 [[nodiscard]] inline [[nodiscard]] inline
28 197 Result read(IO *p_io, ResourceType type, ResourceUnion *p_ru) { Result read(IO *p_io, ResourceType type, ResourceUnion *p_ru) {
29 198 switch(type) { switch(type) {
30 case ResourceType::IMAGE: return p_ru->image .read(p_io);
31 case ResourceType::VERTICES: return p_ru->vertices.read(p_io);
32 case ResourceType::INDICES: return p_ru->indices .read(p_io);
33 case ResourceType::MESH: return p_ru->mesh .read(p_io);
34 case ResourceType::MODEL: return p_ru->model .read(p_io);
35 case ResourceType::SCENE: return p_ru->scene .read(p_io);
36 default: return Result::UNKNOWN_RESOURCE_TYPE;
199 case ResourceType::IMAGE: return read(&p_ru->image, p_io);
200 case ResourceType::VERTICES: return read(&p_ru->vertices, p_io);
201 case ResourceType::INDICES: return read(&p_ru->indices, p_io);
202 case ResourceType::MESH: return read(&p_ru->mesh, p_io);
203 case ResourceType::MODEL: return read(&p_ru->model, p_io);
204 case ResourceType::SCENE: return read(&p_ru->scene, p_io);
205 default: return Result::UNKNOWN_RESOURCE_TYPE;
37 206 } }
38 207 } }
39 208 } }
File include/jrf/scene.h changed (mode: 100644) (index a76e8d3..327a81f)
20 20 #include "model.h" #include "model.h"
21 21 #include <jlib/array.h> #include <jlib/array.h>
22 22
23 namespace jrf { struct Scene; struct SceneEntry; }
24
25 struct jrf::SceneEntry
26 {
27 template<typename IO = jl::io_agent> [[nodiscard]]
28 Result read(IO *p_mediator) {
29 Result res = read_str(p_mediator, &model_path);
30 if (res != Result::SUCCESS)
31 return res;
32 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
33 if (not p_io->read_items(&options.pos))
34 goto CANCEL;
35 if (not p_io->read_items(&options.shift))
36 goto CANCEL;
37 if (not p_io->read_items(&options.transform))
38 goto CANCEL;
39 return Result::SUCCESS;
40 CANCEL: destroy();
41 return Result::MEDIATOR_ERROR;
42 }
43 template<typename IO = jl::io_agent> [[nodiscard]]
44 Result write(IO *p_mediator) const {
45 if (p_mediator->write(model_path.begin(), model_path.size())
46 != int64_t(model_path.size()))
47 return Result::MEDIATOR_ERROR;
48 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
49 if (not p_io->write_items(&options.pos))
50 return Result::MEDIATOR_ERROR;
51 if (not p_io->write_items(&options.shift))
52 return Result::MEDIATOR_ERROR;
53 if (not p_io->write_items(&options.transform))
54 return Result::MEDIATOR_ERROR;
55 return Result::SUCCESS;
23 namespace jrf {
24 struct SceneEntryOptions;
25 struct SceneEntry;
26 struct SceneOptions;
27 struct Scene;
28 }
29 struct jrf::SceneEntryOptions {
30 void set_default() {
31 pos = {};
32 shift = {};
33 transform = {};
34 transform[0] = transform[5] = transform[10] = transform[15] = 1;
56 35 } }
57 struct Options {
58 void set_default() {
59 pos = {};
60 shift = {};
61 transform = {};
62 transform[0] = transform[5] = transform[10] = transform[15] = 1;
63 }
64 jl::array<float, 3> pos; ///< position
65 jl::array<int32_t,3> shift; ///< shift of position
66 jl::array<float, 16> transform; ///< transformation matrix 4x4
67 };
36 jl::array<float, 3> pos; ///< position
37 jl::array<int32_t,3> shift; ///< shift of position
38 jl::array<float, 16> transform; ///< transformation matrix 4x4
39 };
40 struct jrf::SceneEntry {
68 41 void destroy() { void destroy() {
69 42 model_path.destroy(); model_path.destroy();
70 43 } }
71 Options options;
72 jl::string model_path;
44 SceneEntryOptions options;
45 jl::string model_path;
73 46 }; };
74 struct jrf::Scene
75 {
47 struct jrf::SceneOptions {
48 void set_default() {
49 *this = {};
50 }
51 jl::array<int32_t, 3> shift; ///< global shift of scene
52 int32_t shift_po2; ///< Power of two
53 };
54 struct jrf::Scene {
76 55 void destroy() { void destroy() {
77 56 entries.destroy(&SceneEntry::destroy); entries.destroy(&SceneEntry::destroy);
78 57 } }
79 template<typename IO = jl::io_agent> [[nodiscard]]
80 Result read(IO *p_mediator) {
81 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
82 if (not p_io->read_items(&options.shift))
83 return Result::MEDIATOR_ERROR;
84 if (not p_io->read_items(&options.shift_po2))
85 return Result::MEDIATOR_ERROR;
86 uint64_t entry_count;
87 if (not p_io->read_items(&entry_count))
88 return Result::MEDIATOR_ERROR;
89 if (entry_count == 0) {
90 entries.init();
91 return Result::SUCCESS;
92 }
93 if (not entries.init(entry_count))
94 return Result::ALLOCATION_FAIL;
95 for (uint64_t i = 0; i < entry_count; ++i) {
96 Result res = entries[i].read(p_mediator);
97 if (res != Result::SUCCESS) {
98 while(i > 0)
99 entries[--i].destroy();
100 entries.destroy();
101 return res;
102 }
103 }
104 return Result::SUCCESS;
105 }
106 template<typename IO = jl::io_agent> [[nodiscard]]
107 Result write(IO *p_mediator) const {
108 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
109 if (not p_io->write_items(&options.shift))
110 return Result::MEDIATOR_ERROR;
111 if (not p_io->write_items(&options.shift_po2))
112 return Result::MEDIATOR_ERROR;
113 size_t entry_count = entries.count();
114 if (not p_io->write_items(&entry_count))
115 return Result::MEDIATOR_ERROR;
116 for (auto &e : entries) {
117 Result res = e.write(p_mediator);
118 if (res != Result::SUCCESS)
119 return res;
120 }
121 return Result::SUCCESS;
122 }
123 struct Options {
124 void set_default_value() { *this = {}; }
125 jl::array<int32_t, 3> shift; ///< global shift of scene
126 int32_t shift_po2; ///< Power of two
127 };
128 Options options;
58 SceneOptions options;
129 59 jl::rarray<SceneEntry> entries; jl::rarray<SceneEntry> entries;
130 60 }; };
File include/jrf/vertices.h deleted (index f792f45..0000000)
1 /**
2 * Copyright 2020 Damir Valiev
3 *
4 * This file is part of jrf C++ library.
5 *
6 * This library is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this library. If not, see <https://www.gnu.org/licenses/>
18 */
19 #pragma once
20 #include <jlib/io_agent.h>
21 #include <jlib/allocate.h>
22 #include <jlib/array.h>
23 #include "result.h"
24
25 namespace jrf { struct Vertices; }
26 struct jrf::Vertices
27 {
28 void destroy() {
29 jl::deallocate(&p_data);
30 }
31 template<typename IO = jl::io_agent> [[nodiscard]]
32 Result read(IO *p_mediator) {
33 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
34 if (not p_io->read_items(&attributes))
35 return Result::MEDIATOR_ERROR;
36 if (not p_io->read_items(&vecs_count))
37 return Result::MEDIATOR_ERROR;
38 jl::array<size_t, ATTRIBUTE_COUNT> asizes;
39 data_size = 0;
40 for (uint8_t a = 0; a < ATTRIBUTE_COUNT; ++a) {
41 asizes[a] = attributes[a].dimension_count
42 * FORMAT_SIZE[attributes[a].format] * vecs_count;
43 data_size += asizes[a];
44 }
45 for (uint8_t a = 0; a < ATTRIBUTE_COUNT; ++a)
46 if (attributes[a].offset + asizes[a] > data_size)
47 return Result::FILE_CORRUPTED;
48 if (data_size == 0)
49 return Result::FILE_NO_DATA;
50 if (not jl::allocate_bytes(&p_data, data_size))
51 return Result::MEDIATOR_ERROR;
52 if (not p_io->read_bytes(p_data, data_size))
53 return this->destroy(), Result::MEDIATOR_ERROR;
54 return Result::SUCCESS;
55 }
56 template<typename IO = jl::io_agent> [[nodiscard]]
57 Result write(IO *p_mediator) const {
58 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
59 if (not p_io->write_items(&attributes))
60 return Result::MEDIATOR_ERROR;
61 if (not p_io->write_items(&vecs_count))
62 return Result::MEDIATOR_ERROR;
63 if (not p_io->write_bytes(p_data, data_size))
64 return Result::MEDIATOR_ERROR;
65 return Result::SUCCESS;
66 }
67 enum Format : uint16_t {
68 F16, F32, F64,
69 I8, I16, I32, I64,
70 U8, U16, U32, U64
71 };
72 constexpr static const uint8_t FORMAT_SIZE[] = {
73 2, 4, 8,
74 1, 2, 4, 8,
75 1, 2, 4, 8
76 };
77 enum AttributeType {
78 POSITION, TEX_COORD, NORMAL,
79 RESERVED_BEGIN,
80 RESERVED_COUNT = 16
81 };
82 static_assert (RESERVED_BEGIN < RESERVED_COUNT);
83 constexpr static const uint8_t ATTRIBUTE_COUNT = RESERVED_COUNT;
84
85 struct Attribute {
86 uint32_t offset;
87 uint16_t dimension_count;
88 Format format;
89 };
90 using Attributes = jl::array<Attribute, ATTRIBUTE_COUNT>;
91
92 Attributes attributes;
93 uint64_t vecs_count;
94 uint64_t data_size;
95 void *p_data;
96 };
File include/jrf/write.h changed (mode: 100644) (index 751db04..375ed8d)
18 18 */ */
19 19 #pragma once #pragma once
20 20 #include "jrf.h" #include "jrf.h"
21 #include <jlib/io_agent.h>
21 22
22 23 namespace jrf namespace jrf
23 24 { {
25 template<typename IO = jl::io_agent> [[nodiscard]]
26 Result write(const Image &im, IO *p_mediator) {
27 if (p_mediator->write(&im.extent, sizeof(im.extent)) != sizeof(im.extent))
28 return Result::MEDIATOR_ERROR;
29 if (p_mediator->write(&im.format, sizeof(im.format)) != sizeof(im.format))
30 return Result::MEDIATOR_ERROR;
31 if (p_mediator->write(im.p_pixels, im.size) != int64_t(im.size))
32 return Result::MEDIATOR_ERROR;
33 return Result::SUCCESS;
34 }
35 template<typename IO = jl::io_agent> [[nodiscard]]
36 Result write(const Indices &in, IO *p_mediator) {
37 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
38 if (not p_io->write_items(&in.format))
39 return Result::MEDIATOR_ERROR;
40 if (not p_io->write_items(&in.size))
41 return Result::MEDIATOR_ERROR;
42 if (not p_io->write_bytes(in.p_data, in.size))
43 return Result::MEDIATOR_ERROR;
44
45 return Result::SUCCESS;
46 }
47 template<typename T, typename IO = jl::io_agent> [[nodiscard]]
48 Result write(const Data<T> &d, IO *p_io) {
49 if (p_io->write(&d.mode, sizeof(d.mode)) != sizeof(d.mode))
50 return Result::MEDIATOR_ERROR;
51 switch(d.mode) {
52 case ResourceMode::DATA: {
53 Result res = d.u.data.write(p_io);
54 if (res != Result::SUCCESS)
55 return res;
56 } break;
57 case ResourceMode::PATH: {
58 if (p_io->write(d.u.path.begin(), d.u.path.size())
59 != int64_t(d.u.path.size()))
60 return Result::MEDIATOR_ERROR;
61 } break;
62 default: break;
63 }
64 return Result::SUCCESS;
65 }
66 template<typename IO = jl::io_agent> [[nodiscard]]
67 Result write(const Vertices &v, IO *p_mediator) {
68 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
69 if (not p_io->write_items(&v.attributes))
70 return Result::MEDIATOR_ERROR;
71 if (not p_io->write_items(&v.vecs_count))
72 return Result::MEDIATOR_ERROR;
73 if (not p_io->write_bytes(v.p_data, v.data_size))
74 return Result::MEDIATOR_ERROR;
75 return Result::SUCCESS;
76 }
77 template<typename IO = jl::io_agent> [[nodiscard]]
78 Result write(const Mesh &m, IO *p_mediator) {
79 Result res = write(m.vert, p_mediator);
80 if (res != Result::SUCCESS)
81 return res;
82 return write(m.ind, p_mediator);
83 }
84 template<typename IO = jl::io_agent> [[nodiscard]]
85 Result write(const Model &m, IO *p_io) {
86 Result res = write(&m.mesh, p_io);
87 if (res != Result::SUCCESS)
88 return res;
89 return write(&m.image, p_io);
90 }
91 template<typename IO = jl::io_agent> [[nodiscard]]
92 Result write(const SceneEntry &s, IO *p_mediator) {
93 if (p_mediator->write(s.model_path.begin(), s.model_path.size())
94 != int64_t(s.model_path.size()))
95 return Result::MEDIATOR_ERROR;
96 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
97 if (not p_io->write_items(&s.options.pos))
98 return Result::MEDIATOR_ERROR;
99 if (not p_io->write_items(&s.options.shift))
100 return Result::MEDIATOR_ERROR;
101 if (not p_io->write_items(&s.options.transform))
102 return Result::MEDIATOR_ERROR;
103 return Result::SUCCESS;
104 }
105 template<typename IO = jl::io_agent> [[nodiscard]]
106 Result write(const Scene &s, IO *p_mediator) {
107 auto *p_io = jl::io_agent_p_alt_cast(p_mediator);
108 if (not p_io->write_items(&s.options.shift))
109 return Result::MEDIATOR_ERROR;
110 if (not p_io->write_items(&s.options.shift_po2))
111 return Result::MEDIATOR_ERROR;
112 size_t entry_count = s.entries.count();
113 if (not p_io->write_items(&entry_count))
114 return Result::MEDIATOR_ERROR;
115 for (auto &e : s.entries) {
116 Result res = write(&e, p_mediator);
117 if (res != Result::SUCCESS)
118 return res;
119 }
120 return Result::SUCCESS;
121 }
24 122 template<typename IO = jl::io_agent> [[nodiscard]] template<typename IO = jl::io_agent> [[nodiscard]]
25 123 Result write(IO *p_io, ResourceType type, ResourceUnion *p_ru) { Result write(IO *p_io, ResourceType type, ResourceUnion *p_ru) {
26 124 switch(type) { switch(type) {
 
... ... namespace jrf
47 145 header.type = RT; header.type = RT;
48 146 if (p_io->write(&header, sizeof (EntryHeader)) != sizeof(EntryHeader)) if (p_io->write(&header, sizeof (EntryHeader)) != sizeof(EntryHeader))
49 147 return MEDIATOR_ERROR; return MEDIATOR_ERROR;
50 return resource.write(p_io);
148 return write(resource, p_io);
51 149 } }
52 150 } }
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/Jackalope/jrf

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/Jackalope/jrf

Clone this repository using git:
git clone git://git.rocketgit.com/user/Jackalope/jrf

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main