vsg: include/vsg/core/Array3D.h Source File

vsg 1.1.9 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;
37 using iterator = stride_iterator<value_type>;
38 using const_iterator = stride_iterator<const value_type>;
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 _data = _allocate(static_cast<size_t>(_width) * static_cast<size_t>(_height) * static_cast<size_t>(_depth));
54 if (_data)
55 {
56 auto dest_v = _data;
57 for (const auto& v : rhs) *(dest_v++) = v;
58 dirty();
59 }
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(nullptr),
65 _width(width),
66 _height(height),
67 _depth(depth)
68 {
69 _data = _allocate(static_cast<size_t>(_width) * static_cast<size_t>(_height) * static_cast<size_t>(_depth));
70 dirty();
71 }
72
73 Array3D(uint32_t width, uint32_t height, uint32_t depth, value_type* data, Properties in_properties = {}) :
74 Data(in_properties, sizeof(value_type)),
75 _data(data),
76 _width(width),
77 _height(height),
78 _depth(depth) { dirty(); }
79
80 Array3D(uint32_t width, uint32_t height, uint32_t depth, const value_type& value, Properties in_properties = {}) :
81 Data(in_properties, sizeof(value_type)),
82 _data(nullptr),
83 _width(width),
84 _height(height),
85 _depth(depth)
86 {
87 _data = _allocate(static_cast<size_t>(_width) * static_cast<size_t>(_height) * static_cast<size_t>(_depth));
88 if (_data)
89 {
90 for (auto& v : *this) v = value;
91 dirty();
92 }
93 }
94
95 Array3D(ref_ptr<Data> data, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, uint32_t depth, Properties in_properties = {}) :
96 Data(),
97 _data(nullptr),
98 _width(0),
99 _height(0),
100 _depth(0)
101 {
102 assign(data, offset, stride, width, height, depth, in_properties);
103 }
104
105 template<typename... Args>
106 static ref_ptr<Array3D> create(Args&&... args)
107 {
108 return ref_ptr<Array3D>(new Array3D(std::forward<Args>(args)...));
109 }
110
111 ref_ptr<Object> clone(const CopyOp& copyop = {}) const override
112 {
113 return ref_ptr<Array3D>(new Array3D(*this, copyop));
114 }
115
116 size_t sizeofObject() const noexcept override { return sizeof(Array3D); }
117 const char* className() const noexcept override { return type_name<Array3D>(); }
118 const std::type_info& type_info() const noexcept override { return typeid(*this); }
119 bool is_compatible(const std::type_info& type) const noexcept override { return typeid(Array3D) == type || Data::is_compatible(type); }
120
121 // implementation provided by Visitor.h
122 void accept(Visitor& visitor) override;
123 void accept(ConstVisitor& visitor) const override;
124
125 void read(Input& input) override
126 {
127 size_t original_size = size();
128
129 Data::read(input);
130
131 uint32_t w = input.readValue<uint32_t>("width");
132 uint32_t h = input.readValue<uint32_t>("height");
133 uint32_t d = input.readValue<uint32_t>("depth");
134
135 if (auto data_storage = input.readObject<Data>("storage"))
136 {
137 uint32_t offset = input.readValue<uint32_t>("offset");
138 assign(data_storage, offset, properties.stride, w, h, d, properties);
139 return;
140 }
141
142 if (input.matchPropertyName("data"))
143 {
144 size_t new_size = computeValueCountIncludingMipmaps(w, h, d, properties.maxNumMipmaps);
145
146 if (_data) // if data exists already may be able to reuse it
147 {
148 if (original_size != new_size) // if existing data is a different size delete old, and create new
149 {
150 _delete();
151 _data = _allocate(new_size);
152 }
153 }
154 else // allocate space for data
155 {
156 _data = _allocate(new_size);
157 }
158
159 properties.stride = sizeof(value_type);
160 _width = w;
161 _height = h;
162 _depth = d;
163 _storage = nullptr;
164
165 if (_data) input.read(new_size, _data);
166
167 dirty();
168 }
169 }
170
171 void write(Output& output) const override
172 {
173 Data::write(output);
174
175 output.writeValue<uint32_t>("width", _width);
176 output.writeValue<uint32_t>("height", _height);
177 output.writeValue<uint32_t>("depth", _depth);
178
179 output.writeObject("storage", _storage);
180 if (_storage)
181 {
182 auto offset = (reinterpret_cast<uintptr_t>(_data) - reinterpret_cast<uintptr_t>(_storage->dataPointer()));
183 output.writeValue<uint32_t>("offset", offset);
184 return;
185 }
186
187 output.writePropertyName("data");
188 output.write(valueCount(), _data);
189 output.writeEndOfLine();
190 }
191
192 size_t size() const { return (properties.maxNumMipmaps <= 1) ? (static_cast<size_t>(_width) * _height * _depth) : computeValueCountIncludingMipmaps(_width, _height, _depth, properties.maxNumMipmaps); }
193
194 bool available() const { return _data != nullptr; }
195 bool empty() const { return _data == nullptr; }
196
197 void clear()
198 {
199 _delete();
200
201 _width = 0;
202 _height = 0;
203 _depth = 0;
204 _data = nullptr;
205 _storage = nullptr;
206 }
207
208 Array3D& operator=(const Array3D& rhs)
209 {
210 if (&rhs == this) return *this;
211
212 clear();
213
214 properties = rhs.properties;
215 _width = rhs._width;
216 _height = rhs._height;
217 _depth = rhs._depth;
218
219 _data = _allocate(static_cast<size_t>(_width) * static_cast<size_t>(_height) * static_cast<size_t>(_depth));
220 if (_data)
221 {
222 auto dest_v = _data;
223 for (const auto& v : rhs) *(dest_v++) = v;
224 }
225
226 dirty();
227
228 return *this;
229 }
230
231 void assign(uint32_t width, uint32_t height, uint32_t depth, value_type* data, Properties in_properties = {})
232 {
233 _delete();
234
235 properties = in_properties;
236 properties.stride = sizeof(value_type);
237 _width = width;
238 _height = height;
239 _depth = depth;
240 _data = data;
241 _storage = nullptr;
242
243 dirty();
244 }
245
246 void assign(ref_ptr<Data> storage, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, uint32_t depth, Properties in_properties = {})
247 {
248 _delete();
249
250 _storage = storage;
251 properties = in_properties;
252 properties.stride = stride;
253 if (_storage && _storage->dataPointer())
254 {
255 _data = reinterpret_cast<value_type*>(reinterpret_cast<uint8_t*>(_storage->dataPointer()) + offset);
256 _width = width;
257 _height = height;
258 _depth = depth;
259 }
260 else
261 {
262 _data = nullptr;
263 _width = 0;
264 _height = 0;
265 _depth = 0;
266 }
267
268 dirty();
269 }
270
271 // 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.
272 // if the data is stored in a separate vsg::Data object then return nullptr and do not attempt to release data.
273 void* dataRelease() override
274 {
275 if (!_storage)
276 {
277 void* tmp = _data;
278 _data = nullptr;
279 _width = 0;
280 _height = 0;
281 _depth = 0;
282 return tmp;
283 }
284 else
285 {
286 return nullptr;
287 }
288 }
289
290 size_t valueSize() const override { return sizeof(value_type); }
291 size_t valueCount() const override { return size(); }
292
293 bool dataAvailable() const override { return available(); }
294 size_t dataSize() const override { return size() * properties.stride; }
295
296 void* dataPointer() override { return _data; }
297 const void* dataPointer() const override { return _data; }
298
299 void* dataPointer(size_t i) override { return data(i); }
300 const void* dataPointer(size_t i) const override { return data(i); }
301
302 uint32_t dimensions() const override { return 3; }
303
304 uint32_t width() const override { return _width; }
305 uint32_t height() const override { return _height; }
306 uint32_t depth() const override { return _depth; }
307
308 value_type* data() { return _data; }
309 const value_type* data() const { return _data; }
310
311 inline value_type* data(size_t i) { return reinterpret_cast<value_type*>(reinterpret_cast<uint8_t*>(_data) + i * static_cast<size_t>(properties.stride)); }
312 inline const value_type* data(size_t i) const { return reinterpret_cast<const value_type*>(reinterpret_cast<const uint8_t*>(_data) + i * static_cast<size_t>(properties.stride)); }
313
314 size_t index(uint32_t i, uint32_t j, uint32_t k) const noexcept { return static_cast<size_t>(static_cast<size_t>(k) * static_cast<size_t>(_width) * static_cast<size_t>(_height) + static_cast<size_t>(j) * static_cast<size_t>(_width) + static_cast<size_t>(i)); }
315
316 value_type& operator[](size_t i) { return *data(i); }
317 const value_type& operator[](size_t i) const { return *data(i); }
318
319 value_type& at(size_t i) { return *data(i); }
320 const value_type& at(size_t i) const { return *data(i); }
321
322 value_type& operator()(uint32_t i, uint32_t j, uint32_t k) { return *data(index(i, j, k)); }
323 const value_type& operator()(uint32_t i, uint32_t j, uint32_t k) const { return *data(index(i, j, k)); }
324
325 value_type& at(uint32_t i, uint32_t j, uint32_t k) { return *data(index(i, j, k)); }
326 const value_type& at(uint32_t i, uint32_t j, uint32_t k) const { return *data(index(i, j, k)); }
327
328 void set(size_t i, const value_type& v) { *data(i) = v; }
329 void set(uint32_t i, uint32_t j, uint32_t k, const value_type& v) { *data(index(i, j, k)) = v; }
330
331 Data* storage() { return _storage; }
332 const Data* storage() const { return _storage; }
333
334 iterator begin() { return iterator{_data, properties.stride}; }
335 const_iterator begin() const { return const_iterator{_data, properties.stride}; }
336
337 iterator end() { return iterator{data(_width * _height * _depth), properties.stride}; }
338 const_iterator end() const { return const_iterator{data(_width * _height * _depth), properties.stride}; }
339
340 protected:
341 virtual ~Array3D()
342 {
343 _delete();
344 }
345
346 value_type* _allocate(size_t size) const
347 {
348 if (size == 0)
349 return nullptr;
350 else if (properties.allocatorType == ALLOCATOR_TYPE_NEW_DELETE)
351 return new value_type[size];
352 else if (properties.allocatorType == ALLOCATOR_TYPE_MALLOC_FREE)
353 return new (std::malloc(sizeof(value_type) * size)) value_type[size];
354 else
355 return new (vsg::allocate(sizeof(value_type) * size, ALLOCATOR_AFFINITY_DATA)) value_type[size];
356 }
357
358 void _delete()
359 {
360 if (!_storage && _data)
361 {
362 if (properties.allocatorType == ALLOCATOR_TYPE_NEW_DELETE)
363 delete[] _data;
364 else if (properties.allocatorType == ALLOCATOR_TYPE_MALLOC_FREE)
365 std::free(_data);
366 else if (properties.allocatorType != 0)
367 vsg::deallocate(_data);
368 }
369 }
370
371 private:
372 value_type* _data;
373 uint32_t _width;
374 uint32_t _height;
375 uint32_t _depth;
376 ref_ptr<Data> _storage;
377 };
378
379 VSG_array3D(byteArray3D, int8_t);
380 VSG_array3D(ubyteArray3D, uint8_t);
381 VSG_array3D(shortArray3D, int16_t);
382 VSG_array3D(ushortArray3D, uint16_t);
383 VSG_array3D(intArray3D, int32_t);
384 VSG_array3D(uintArray3D, uint32_t);
385 VSG_array3D(floatArray3D, float);
386 VSG_array3D(doubleArray3D, double);
387
388 VSG_array3D(vec2Array3D, vec2);
389 VSG_array3D(vec3Array3D, vec3);
390 VSG_array3D(vec4Array3D, vec4);
391
392 VSG_array3D(dvec2Array3D, dvec2);
393 VSG_array3D(dvec3Array3D, dvec3);
394 VSG_array3D(dvec4Array3D, dvec4);
395
396 VSG_array3D(svec2Array3D, svec2);
397 VSG_array3D(svec3Array3D, svec3);
398 VSG_array3D(svec4Array3D, svec4);
399
400 VSG_array3D(usvec2Array3D, usvec2);
401 VSG_array3D(usvec3Array3D, usvec3);
402 VSG_array3D(usvec4Array3D, usvec4);
403
404 VSG_array3D(ubvec2Array3D, ubvec2);
405 VSG_array3D(ubvec3Array3D, ubvec3);
406 VSG_array3D(ubvec4Array3D, ubvec4);
407
408 VSG_array3D(block64Array3D, block64);
409 VSG_array3D(block128Array3D, block128);
410
411} // namespace vsg
vsg::Array3D
Definition Array3D.h:34
vsg::Array3D::type_info
const std::type_info & type_info() const noexcept override
return the std::type_info of this Object
Definition Array3D.h:118
vsg::Array3D::clone
ref_ptr< Object > clone(const CopyOp &copyop={}) const override
Definition Array3D.h:111
vsg::CopyOp
Definition Object.h:42
vsg::Data::properties
Properties properties
properties of the data such as format, origin, stride, dataVariance etc.
Definition Data.h:164
vsg::Data::dirty
void dirty()
increment the ModifiedCount to signify the data has been modified
Definition Data.h:197
vsg::ref_ptr
Definition ref_ptr.h:22
vsg::Data::Properties
Definition Data.h:116
vsg::block128
Definition Data.h:46
vsg::block64
Definition Data.h:40
vsg::stride_iterator
Definition Data.h:66