PolyVox  0.2.1
Open source voxel management library
Serialization.inl
Go to the documentation of this file.
1 /*******************************************************************************
2 Copyright (c) 2005-2009 David Williams
3 
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7 
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11 
12  1. The origin of this software must not be misrepresented; you must not
13  claim that you wrote the original software. If you use this software
14  in a product, an acknowledgment in the product documentation would be
15  appreciated but is not required.
16 
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19 
20  3. This notice may not be removed or altered from any source
21  distribution.
22 *******************************************************************************/
23 
24 namespace PolyVox
25 {
26  //Note: we don't do much error handling in here - exceptions will simply be propergated up to the caller.
27  //FIXME - think about pointer ownership issues. Or could return volume by value if the copy constructor is shallow
28  template< typename VolumeType >
29  polyvox_shared_ptr< VolumeType > loadVolumeRaw(std::istream& stream, VolumeSerializationProgressListener* progressListener)
30  {
31  assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'loadVolume()' ASAP.
32 
33  //Read volume dimensions
34  uint8_t volumeWidthPower = 0;
35  uint8_t volumeHeightPower = 0;
36  uint8_t volumeDepthPower = 0;
37  stream.read(reinterpret_cast<char*>(&volumeWidthPower), sizeof(volumeWidthPower));
38  stream.read(reinterpret_cast<char*>(&volumeHeightPower), sizeof(volumeHeightPower));
39  stream.read(reinterpret_cast<char*>(&volumeDepthPower), sizeof(volumeDepthPower));
40 
41  uint16_t volumeWidth = 0x0001 << volumeWidthPower;
42  uint16_t volumeHeight = 0x0001 << volumeHeightPower;
43  uint16_t volumeDepth = 0x0001 << volumeDepthPower;
44 
45  //FIXME - need to support non cubic volumes
46  polyvox_shared_ptr< VolumeType > volume(new LargeVolume<VolumeType::VoxelType>(volumeWidth, volumeHeight, volumeDepth));
47 
48  //Read data
49  for(uint16_t z = 0; z < volumeDepth; ++z)
50  {
51  //Update progress once per slice.
52  if(progressListener)
53  {
54  float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
55  progressListener->onProgressUpdated(fProgress);
56  }
57 
58  for(uint16_t y = 0; y < volumeHeight; ++y)
59  {
60  for(uint16_t x = 0; x < volumeWidth; ++x)
61  {
62  VolumeType::VoxelType value;
63  stream.read(reinterpret_cast<char*>(&value), sizeof(value));
64 
65  volume->setVoxelAt(x,y,z,value);
66  }
67  }
68  }
69 
70  //Finished
71  if(progressListener)
72  {
73  progressListener->onProgressUpdated(1.0f);
74  }
75 
76  return volume;
77  }
78 
79  template< typename VolumeType >
80  void saveVolumeRaw(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener)
81  {
82  assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'saveVolume()' ASAP.
83 
84  //Write volume dimensions
85  uint16_t volumeWidth = volume.getWidth();
86  uint16_t volumeHeight = volume.getHeight();
87  uint16_t volumeDepth = volume.getDepth();
88 
89  uint8_t volumeWidthPower = logBase2(volumeWidth);
90  uint8_t volumeHeightPower = logBase2(volumeHeight);
91  uint8_t volumeDepthPower = logBase2(volumeDepth);
92 
93  stream.write(reinterpret_cast<char*>(&volumeWidthPower), sizeof(volumeWidthPower));
94  stream.write(reinterpret_cast<char*>(&volumeHeightPower), sizeof(volumeHeightPower));
95  stream.write(reinterpret_cast<char*>(&volumeDepthPower), sizeof(volumeDepthPower));
96 
97  //Write data
98  VolumeType::Sampler volIter(&volume);
99  for(uint16_t z = 0; z < volumeDepth; ++z)
100  {
101  //Update progress once per slice.
102  if(progressListener)
103  {
104  float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
105  progressListener->onProgressUpdated(fProgress);
106  }
107 
108  for(uint16_t y = 0; y < volumeHeight; ++y)
109  {
110  for(uint16_t x = 0; x < volumeWidth; ++x)
111  {
112  volIter.setPosition(x,y,z);
113  VolumeType::VoxelType value = volIter.getVoxel();
114  stream.write(reinterpret_cast<char*>(&value), sizeof(value));
115  }
116  }
117  }
118 
119  //Finished
120  if(progressListener)
121  {
122  progressListener->onProgressUpdated(1.0f);
123  }
124  }
125 
126  //Note: we don't do much error handling in here - exceptions will simply be propergated up to the caller.
127  //FIXME - think about pointer ownership issues. Or could return volume by value if the copy constructor is shallow
128  template< typename VolumeType >
129  polyvox_shared_ptr< VolumeType > loadVolumeRle(std::istream& stream, VolumeSerializationProgressListener* progressListener)
130  {
131  assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'loadVolume()' ASAP.
132 
133  //Read volume dimensions
134  uint8_t volumeWidthPower = 0;
135  uint8_t volumeHeightPower = 0;
136  uint8_t volumeDepthPower = 0;
137  stream.read(reinterpret_cast<char*>(&volumeWidthPower), sizeof(volumeWidthPower));
138  stream.read(reinterpret_cast<char*>(&volumeHeightPower), sizeof(volumeHeightPower));
139  stream.read(reinterpret_cast<char*>(&volumeDepthPower), sizeof(volumeDepthPower));
140 
141  uint16_t volumeWidth = 0x0001 << volumeWidthPower;
142  uint16_t volumeHeight = 0x0001 << volumeHeightPower;
143  uint16_t volumeDepth = 0x0001 << volumeDepthPower;
144 
145  //FIXME - need to support non cubic volumes
146  polyvox_shared_ptr< VolumeType > volume(new LargeVolume<VolumeType::VoxelType>(volumeWidth, volumeHeight, volumeDepth));
147 
148  //Read data
149  bool firstTime = true;
150  uint32_t runLength = 0;
151  VolumeType::VoxelType value;
152  stream.read(reinterpret_cast<char*>(&value), sizeof(value));
153  stream.read(reinterpret_cast<char*>(&runLength), sizeof(runLength));
154  for(uint16_t z = 0; z < volumeDepth; ++z)
155  {
156  //Update progress once per slice.
157  if(progressListener)
158  {
159  float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
160  progressListener->onProgressUpdated(fProgress);
161  }
162 
163  for(uint16_t y = 0; y < volumeHeight; ++y)
164  {
165  for(uint16_t x = 0; x < volumeWidth; ++x)
166  {
167  if(runLength != 0)
168  {
169  volume->setVoxelAt(x,y,z,value);
170  runLength--;
171  }
172  else
173  {
174  stream.read(reinterpret_cast<char*>(&value), sizeof(value));
175  stream.read(reinterpret_cast<char*>(&runLength), sizeof(runLength));
176 
177  volume->setVoxelAt(x,y,z,value);
178  runLength--;
179  }
180  }
181  }
182  }
183 
184  //Finished
185  if(progressListener)
186  {
187  progressListener->onProgressUpdated(1.0f);
188  }
189 
190  return volume;
191  }
192 
193  template< typename VolumeType >
194  void saveVolumeRle(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener)
195  {
196  assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'saveVolume()' ASAP.
197 
198  //Write volume dimensions
199  uint16_t volumeWidth = volume.getWidth();
200  uint16_t volumeHeight = volume.getHeight();
201  uint16_t volumeDepth = volume.getDepth();
202 
203  uint8_t volumeWidthPower = logBase2(volumeWidth);
204  uint8_t volumeHeightPower = logBase2(volumeHeight);
205  uint8_t volumeDepthPower = logBase2(volumeDepth);
206 
207  stream.write(reinterpret_cast<char*>(&volumeWidthPower), sizeof(volumeWidthPower));
208  stream.write(reinterpret_cast<char*>(&volumeHeightPower), sizeof(volumeHeightPower));
209  stream.write(reinterpret_cast<char*>(&volumeDepthPower), sizeof(volumeDepthPower));
210 
211  //Write data
212  VolumeType::Sampler volIter(&volume);
213  VolumeType::VoxelType current;
214  uint32_t runLength = 0;
215  bool firstTime = true;
216  for(uint16_t z = 0; z < volumeDepth; ++z)
217  {
218  //Update progress once per slice.
219  if(progressListener)
220  {
221  float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
222  progressListener->onProgressUpdated(fProgress);
223  }
224 
225  for(uint16_t y = 0; y < volumeHeight; ++y)
226  {
227  for(uint16_t x = 0; x < volumeWidth; ++x)
228  {
229  volIter.setPosition(x,y,z);
230  VolumeType::VoxelType value = volIter.getVoxel();
231  if(firstTime)
232  {
233  current = value;
234  runLength = 1;
235  firstTime = false;
236  }
237  else
238  {
239  if(value == current)
240  {
241  runLength++;
242  }
243  else
244  {
245  stream.write(reinterpret_cast<char*>(&current), sizeof(current));
246  stream.write(reinterpret_cast<char*>(&runLength), sizeof(runLength));
247  current = value;
248  runLength = 1;
249  }
250  }
251  }
252  }
253  }
254  stream.write(reinterpret_cast<char*>(&current), sizeof(current));
255  stream.write(reinterpret_cast<char*>(&runLength), sizeof(runLength));
256 
257  //Finished
258  if(progressListener)
259  {
260  progressListener->onProgressUpdated(1.0f);
261  }
262  }
263 
265  // New version of load/save code with versioning
267 
268  template< typename VolumeType >
269  bool loadVolume(std::istream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener)
270  {
271  char pIdentifier[8];
272  stream.read(pIdentifier, 7);
273  pIdentifier[7] = '\0'; //Set the null terminator
274  if(strcmp(pIdentifier, "PolyVox") != 0)
275  {
276  return false;
277  }
278 
279  uint16_t uVersion;
280  stream.read(reinterpret_cast<char*>(&uVersion), sizeof(uVersion));
281 
282  switch(uVersion)
283  {
284  case 0:
285  return loadVersion0(stream, volume, progressListener);
286  //Return means no need to break...
287  default:
288  return false;
289  }
290 
291  }
292 
293  template< typename VolumeType >
294  bool saveVolume(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener)
295  {
296  char pIdentifier[] = "PolyVox";
297  stream.write(pIdentifier, 7);
298 
299  uint16_t uVersion = 0;
300  stream.write(reinterpret_cast<const char*>(&uVersion), sizeof(uVersion));
301 
302  return saveVersion0(stream, volume, progressListener);
303  }
304 
305  //Note: we don't do much error handling in here - exceptions will simply be propergated up to the caller.
306  //FIXME - think about pointer ownership issues. Or could return volume by value if the copy constructor is shallow
307  template< typename VolumeType >
308  bool loadVersion0(std::istream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener)
309  {
310  //Read volume dimensions
311  uint16_t volumeWidth = 0;
312  uint16_t volumeHeight = 0;
313  uint16_t volumeDepth = 0;
314  stream.read(reinterpret_cast<char*>(&volumeWidth), sizeof(volumeWidth));
315  stream.read(reinterpret_cast<char*>(&volumeHeight), sizeof(volumeHeight));
316  stream.read(reinterpret_cast<char*>(&volumeDepth), sizeof(volumeDepth));
317 
318  //Resize the volume
319  //HACK - Forces block size to 32. This functions needs reworking anyway due to large volume support.
320  volume.resize(Region(Vector3DInt32(0,0,0), Vector3DInt32(volumeWidth-1, volumeHeight-1, volumeDepth-1)), 32);
321 
322  //Read data
323  bool firstTime = true;
324  uint32_t runLength = 0;
325  VolumeType::VoxelType value;
326  stream.read(reinterpret_cast<char*>(&value), sizeof(value));
327  stream.read(reinterpret_cast<char*>(&runLength), sizeof(runLength));
328  for(uint16_t z = 0; z < volumeDepth; ++z)
329  {
330  //Update progress once per slice.
331  if(progressListener)
332  {
333  float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
334  progressListener->onProgressUpdated(fProgress);
335  }
336 
337  for(uint16_t y = 0; y < volumeHeight; ++y)
338  {
339  for(uint16_t x = 0; x < volumeWidth; ++x)
340  {
341  if(runLength != 0)
342  {
343  volume.setVoxelAt(x,y,z,value);
344  runLength--;
345  }
346  else
347  {
348  stream.read(reinterpret_cast<char*>(&value), sizeof(value));
349  stream.read(reinterpret_cast<char*>(&runLength), sizeof(runLength));
350 
351  volume.setVoxelAt(x,y,z,value);
352  runLength--;
353  }
354  }
355  }
356  }
357 
358  //Finished
359  if(progressListener)
360  {
361  progressListener->onProgressUpdated(1.0f);
362  }
363 
364  return true;
365  }
366 
367  template< typename VolumeType >
368  bool saveVersion0(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener)
369  {
370  //Write volume dimensions
371  uint16_t volumeWidth = volume.getWidth();
372  uint16_t volumeHeight = volume.getHeight();
373  uint16_t volumeDepth = volume.getDepth();
374 
375  stream.write(reinterpret_cast<char*>(&volumeWidth), sizeof(volumeWidth));
376  stream.write(reinterpret_cast<char*>(&volumeHeight), sizeof(volumeHeight));
377  stream.write(reinterpret_cast<char*>(&volumeDepth), sizeof(volumeDepth));
378 
379  //Write data
380  VolumeType::Sampler volIter(&volume);
381  VolumeType::VoxelType current;
382  uint32_t runLength = 0;
383  bool firstTime = true;
384  for(uint16_t z = 0; z < volumeDepth; ++z)
385  {
386  //Update progress once per slice.
387  if(progressListener)
388  {
389  float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
390  progressListener->onProgressUpdated(fProgress);
391  }
392 
393  for(uint16_t y = 0; y < volumeHeight; ++y)
394  {
395  for(uint16_t x = 0; x < volumeWidth; ++x)
396  {
397  volIter.setPosition(x,y,z);
398  VolumeType::VoxelType value = volIter.getVoxel();
399  if(firstTime)
400  {
401  current = value;
402  runLength = 1;
403  firstTime = false;
404  }
405  else
406  {
407  if(value == current)
408  {
409  runLength++;
410  }
411  else
412  {
413  stream.write(reinterpret_cast<char*>(&current), sizeof(current));
414  stream.write(reinterpret_cast<char*>(&runLength), sizeof(runLength));
415  current = value;
416  runLength = 1;
417  }
418  }
419  }
420  }
421  }
422  stream.write(reinterpret_cast<char*>(&current), sizeof(current));
423  stream.write(reinterpret_cast<char*>(&runLength), sizeof(runLength));
424 
425  //Finished
426  if(progressListener)
427  {
428  progressListener->onProgressUpdated(1.0f);
429  }
430 
431  return true;
432  }
433 }