vsg 1.1.3
VulkanSceneGraph library
Loading...
Searching...
No Matches
Array3D.h
1#pragma once
2
3/* <editor-fold desc="MIT License">
4
5Copyright(c) 2018 Robert Osfield
6
7Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
9The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
11THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12
13</editor-fold> */
14
15#include <vsg/core/Data.h>
16
17#include <vsg/maths/mat4.h>
18#include <vsg/maths/vec2.h>
19#include <vsg/maths/vec3.h>
20#include <vsg/maths/vec4.h>
21
22#include <vsg/io/Input.h>
23#include <vsg/io/Output.h>
24
25#define VSG_array3D(N, T) \
26 using N = Array3D<T>; \
27 template<> \
28 constexpr const char* type_name<N>() noexcept { return "vsg::" #N; }
29
30namespace vsg
31{
32 template<typename T>
33 class Array3D : public Data
34 {
35 public:
36 using value_type = T;
39
40 Array3D() :
41 _data(nullptr),
42 _width(0),
43 _height(0),
44 _depth(0) {}
45
46 Array3D(const Array3D& rhs, const CopyOp copyop = {}) :
47 Data(rhs, copyop),
48 _data(nullptr),
49 _width(rhs._width),
50 _height(rhs._height),
51 _depth(rhs._depth)
52 {
53 if (_width != 0 && _height != 0 && _depth != 0)
54 {
55 _data = _allocate(_width * _height * _depth);
56 auto dest_v = _data;
57 for (auto& v : rhs) *(dest_v++) = v;
58 }
59 dirty();
60 }
61
62 Array3D(uint32_t width, uint32_t height, uint32_t depth, Properties in_properties = {}) :
63 Data(in_properties, sizeof(value_type)),
64 _data(_allocate(width * height * depth)),
65 _width(width),
66 _height(height),
67 _depth(depth)
68 {
69 dirty();
70 }
71
72 Array3D(uint32_t width, uint32_t height, uint32_t depth, value_type* data, Properties in_properties = {}) :
73 Data(in_properties, sizeof(value_type)),
74 _data(data),
75 _width(width),
76 _height(height),
77 _depth(depth) { dirty(); }
78
79 Array3D(uint32_t width, uint32_t height, uint32_t depth, const value_type& value, Properties in_properties = {}) :
80 Data(in_properties, sizeof(value_type)),
81 _data(_allocate(width * height * depth)),
82 _width(width),
83 _height(height),
84 _depth(depth)
85 {
86 for (auto& v : *this) v = value;
87 dirty();
88 }
89
90 Array3D(ref_ptr<Data> data, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, uint32_t depth, Properties in_properties = {}) :
91 Data(),
92 _data(nullptr),
93 _width(0),
94 _height(0),
95 _depth(0)
96 {
97 assign(data, offset, stride, width, height, depth, in_properties);
98 }
99
100 template<typename... Args>
101 static ref_ptr<Array3D> create(Args&&... args)
102 {
103 return ref_ptr<Array3D>(new Array3D(std::forward<Args>(args)...));
104 }
105
106 ref_ptr<Object> clone(const CopyOp& copyop = {}) const override
107 {
108 return ref_ptr<Array3D>(new Array3D(*this, copyop));
109 }
110
111 size_t sizeofObject() const noexcept override { return sizeof(Array3D); }
112 const char* className() const noexcept override { return type_name<Array3D>(); }
113 const std::type_info& type_info() const noexcept override { return typeid(*this); }
114 bool is_compatible(const std::type_info& type) const noexcept override { return typeid(Array3D) == type || Data::is_compatible(type); }
115
116 // implementation provided by Visitor.h
117 void accept(Visitor& visitor) override;
118 void accept(ConstVisitor& visitor) const override;
119
120 void read(Input& input) override
121 {
122 size_t original_size = size();
123
124 Data::read(input);
125
126 uint32_t w = input.readValue<uint32_t>("width");
127 uint32_t h = input.readValue<uint32_t>("height");
128 uint32_t d = input.readValue<uint32_t>("depth");
129
130 if (auto data_storage = input.readObject<Data>("storage"))
131 {
132 uint32_t offset = input.readValue<uint32_t>("offset");
133 assign(data_storage, offset, properties.stride, w, h, d, properties);
134 return;
135 }
136
137 if (input.matchPropertyName("data"))
138 {
139 size_t new_size = computeValueCountIncludingMipmaps(w, h, d, properties.maxNumMipmaps);
140
141 if (_data) // if data exists already may be able to reuse it
142 {
143 if (original_size != new_size) // if existing data is a different size delete old, and create new
144 {
145 _delete();
146 _data = _allocate(new_size);
147 }
148 }
149 else // allocate space for data
150 {
151 _data = _allocate(new_size);
152 }
153
154 properties.stride = sizeof(value_type);
155 _width = w;
156 _height = h;
157 _depth = d;
158 _storage = nullptr;
159
160 if (_data) input.read(new_size, _data);
161
162 dirty();
163 }
164 }
165
166 void write(Output& output) const override
167 {
168 Data::write(output);
169
170 output.writeValue<uint32_t>("width", _width);
171 output.writeValue<uint32_t>("height", _height);
172 output.writeValue<uint32_t>("depth", _depth);
173
174 output.writeObject("storage", _storage);
175 if (_storage)
176 {
177 auto offset = (reinterpret_cast<uintptr_t>(_data) - reinterpret_cast<uintptr_t>(_storage->dataPointer()));
178 output.writeValue<uint32_t>("offset", offset);
179 return;
180 }
181
182 output.writePropertyName("data");
183 output.write(valueCount(), _data);
184 output.writeEndOfLine();
185 }
186
187 size_t size() const { return (properties.maxNumMipmaps <= 1) ? (static_cast<size_t>(_width) * _height * _depth) : computeValueCountIncludingMipmaps(_width, _height, _depth, properties.maxNumMipmaps); }
188
189 bool available() const { return _data != nullptr; }
190 bool empty() const { return _data == nullptr; }
191
192 void clear()
193 {
194 _delete();
195
196 _width = 0;
197 _height = 0;
198 _depth = 0;
199 _data = nullptr;
200 _storage = nullptr;
201 }
202
203 Array3D& operator=(const Array3D& rhs)
204 {
205 if (&rhs == this) return *this;
206
207 clear();
208
209 properties = rhs.properties;
210 _width = rhs._width;
211 _height = rhs._height;
212 _depth = rhs._depth;
213
214 if (_width != 0 && _height != 0 && _depth != 0)
215 {
216 _data = _allocate(_width * _height * _depth);
217 auto dest_v = _data;
218 for (auto& v : rhs) *(dest_v++) = v;
219 }
220
221 dirty();
222
223 return *this;
224 }
225
226 void assign(uint32_t width, uint32_t height, uint32_t depth, value_type* data, Properties in_properties = {})
227 {
228 _delete();
229
230 properties = in_properties;
231 properties.stride = sizeof(value_type);
232 _width = width;
233 _height = height;
234 _depth = depth;
235 _data = data;
236 _storage = nullptr;
237
238 dirty();
239 }
240
241 void assign(ref_ptr<Data> storage, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, uint32_t depth, Properties in_properties = {})
242 {
243 _delete();
244
245 _storage = storage;
246 properties = in_properties;
247 properties.stride = stride;
248 if (_storage && _storage->dataPointer())
249 {
250 _data = reinterpret_cast<value_type*>(reinterpret_cast<uint8_t*>(_storage->dataPointer()) + offset);
251 _width = width;
252 _height = height;
253 _depth = depth;
254 }
255 else
256 {
257 _data = nullptr;
258 _width = 0;
259 _height = 0;
260 _depth = 0;
261 }
262
263 dirty();
264 }
265
266 // release the data so that ownership can be passed on, the local data pointer and size is set to 0 so that destruction of Array will not result in the data being deleted.
267 // if the data is stored in a separate vsg::Data object then return nullptr and do not attempt to release data.
268 void* dataRelease() override
269 {
270 if (!_storage)
271 {
272 void* tmp = _data;
273 _data = nullptr;
274 _width = 0;
275 _height = 0;
276 _depth = 0;
277 return tmp;
278 }
279 else
280 {
281 return nullptr;
282 }
283 }
284
285 size_t valueSize() const override { return sizeof(value_type); }
286 size_t valueCount() const override { return size(); }
287
288 bool dataAvailable() const override { return available(); }
289 size_t dataSize() const override { return size() * properties.stride; }
290
291 void* dataPointer() override { return _data; }
292 const void* dataPointer() const override { return _data; }
293
294 void* dataPointer(size_t i) override { return data(i); }
295 const void* dataPointer(size_t i) const override { return data(i); }
296
297 uint32_t dimensions() const override { return 3; }
298
299 uint32_t width() const override { return _width; }
300 uint32_t height() const override { return _height; }
301 uint32_t depth() const override { return _depth; }
302
303 value_type* data() { return _data; }
304 const value_type* data() const { return _data; }
305
306 inline value_type* data(size_t i) { return reinterpret_cast<value_type*>(reinterpret_cast<uint8_t*>(_data) + i * properties.stride); }
307 inline const value_type* data(size_t i) const { return reinterpret_cast<const value_type*>(reinterpret_cast<const uint8_t*>(_data) + i * properties.stride); }
308
309 size_t index(uint32_t i, uint32_t j, uint32_t k) const noexcept { return static_cast<size_t>(k * _width * _height + j * _width + i); }
310
311 value_type& operator[](size_t i) { return *data(i); }
312 const value_type& operator[](size_t i) const { return *data(i); }
313
314 value_type& at(size_t i) { return *data(i); }
315 const value_type& at(size_t i) const { return *data(i); }
316
317 value_type& operator()(uint32_t i, uint32_t j, uint32_t k) { return *data(index(i, j, k)); }
318 const value_type& operator()(uint32_t i, uint32_t j, uint32_t k) const { return *data(index(i, j, k)); }
319
320 value_type& at(uint32_t i, uint32_t j, uint32_t k) { return *data(index(i, j, k)); }
321 const value_type& at(uint32_t i, uint32_t j, uint32_t k) const { return *data(index(i, j, k)); }
322
323 void set(size_t i, const value_type& v) { *data(i) = v; }
324 void set(uint32_t i, uint32_t j, uint32_t k, const value_type& v) { *data(index(i, j, k)) = v; }
325
326 Data* storage() { return _storage; }
327 const Data* storage() const { return _storage; }
328
329 iterator begin() { return iterator{_data, properties.stride}; }
330 const_iterator begin() const { return const_iterator{_data, properties.stride}; }
331
332 iterator end() { return iterator{data(_width * _height * _depth), properties.stride}; }
333 const_iterator end() const { return const_iterator{data(_width * _height * _depth), properties.stride}; }
334
335 protected:
336 virtual ~Array3D()
337 {
338 _delete();
339 }
340
341 value_type* _allocate(size_t size) const
342 {
343 if (size == 0)
344 return nullptr;
345 else if (properties.allocatorType == ALLOCATOR_TYPE_NEW_DELETE)
346 return new value_type[size];
347 else if (properties.allocatorType == ALLOCATOR_TYPE_MALLOC_FREE)
348 return new (std::malloc(sizeof(value_type) * size)) value_type[size];
349 else
350 return new (vsg::allocate(sizeof(value_type) * size, ALLOCATOR_AFFINITY_DATA)) value_type[size];
351 }
352
353 void _delete()
354 {
355 if (!_storage && _data)
356 {
357 if (properties.allocatorType == ALLOCATOR_TYPE_NEW_DELETE)
358 delete[] _data;
359 else if (properties.allocatorType == ALLOCATOR_TYPE_MALLOC_FREE)
360 std::free(_data);
361 else if (properties.allocatorType != 0)
362 vsg::deallocate(_data);
363 }
364 }
365
366 private:
367 value_type* _data;
368 uint32_t _width;
369 uint32_t _height;
370 uint32_t _depth;
371 ref_ptr<Data> _storage;
372 };
373
374 VSG_array3D(byteArray3D, int8_t);
375 VSG_array3D(ubyteArray3D, uint8_t);
376 VSG_array3D(shortArray3D, int16_t);
377 VSG_array3D(ushortArray3D, uint16_t);
378 VSG_array3D(intArray3D, int32_t);
379 VSG_array3D(uintArray3D, uint32_t);
380 VSG_array3D(floatArray3D, float);
381 VSG_array3D(doubleArray3D, double);
382
383 VSG_array3D(vec2Array3D, vec2);
384 VSG_array3D(vec3Array3D, vec3);
385 VSG_array3D(vec4Array3D, vec4);
386
387 VSG_array3D(dvec2Array3D, dvec2);
388 VSG_array3D(dvec3Array3D, dvec3);
389 VSG_array3D(dvec4Array3D, dvec4);
390
391 VSG_array3D(ubvec2Array3D, ubvec2);
392 VSG_array3D(ubvec3Array3D, ubvec3);
393 VSG_array3D(ubvec4Array3D, ubvec4);
394
395 VSG_array3D(block64Array3D, block64);
396 VSG_array3D(block128Array3D, block128);
397
398} // namespace vsg
Definition Array3D.h:34
const std::type_info & type_info() const noexcept override
return the std::type_info of this Object
Definition Array3D.h:113
ref_ptr< Object > clone(const CopyOp &copyop={}) const override
Definition Array3D.h:106
Definition Object.h:42
Definition Data.h:110
Properties properties
properties of the data such as format, origin, stride, dataVariance etc.
Definition Data.h:164
void dirty()
increment the ModifiedCount to signify the data has been modified
Definition Data.h:197
Definition ref_ptr.h:22
Definition Data.h:116
AllocatorType allocatorType
hint as to how the data values may change during the lifetime of the vsg::Data.
Definition Data.h:131
Definition Data.h:66