3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 (c) 2010 Perttu Ahola <celeron55@gmail.com>
24 #include "heightmap.h"
33 ValueGenerator* ValueGenerator::deSerialize(std::string line)
35 std::istringstream ss(line);
36 //ss.imbue(std::locale("C"));
39 std::getline(ss, name, ' ');
41 if(name == "constant")
46 return new ConstantGenerator(value);
48 else if(name == "linear")
57 return new LinearGenerator(height, slope);
59 else if(name == "power")
70 return new PowerGenerator(height, slope, power);
74 throw SerializationError
75 ("Invalid heightmap generator (deSerialize)");
83 f32 FixedHeightmap::avgNeighbours(v2s16 p, s16 d)
93 for(u16 i=0; i<4; i++){
94 v2s16 p2 = p + dirs[i] * d;
95 f32 n = getGroundHeightParent(p2);
96 if(n < GROUNDHEIGHT_VALID_MINVALUE)
101 assert(count > 0.001);
105 f32 FixedHeightmap::avgDiagNeighbours(v2s16 p, s16 d)
115 for(u16 i=0; i<4; i++){
116 v2s16 p2 = p + dirs[i] * d;
117 f32 n = getGroundHeightParent(p2);
118 if(n < GROUNDHEIGHT_VALID_MINVALUE)
123 assert(count > 0.001);
128 Adds a point to transform into a diamond pattern
129 center = Center of the diamond phase (center of a square)
130 a = Side length of the existing square (2, 4, 8, ...)
132 Adds the center points of the next squares to next_squares as
135 void FixedHeightmap::makeDiamond(
139 core::map<v2s16, bool> &next_squares)
141 /*dstream<<"makeDiamond(): center="
142 <<"("<<center.X<<","<<center.Y<<")"
143 <<", a="<<a<<", randmax="<<randmax
144 <<", next_squares.size()="<<next_squares.size()
147 f32 n = avgDiagNeighbours(center, a/2);
148 // Add (-1.0...1.0) * randmax
149 n += ((float)myrand() / (float)(MYRAND_MAX/2) - 1.0)*randmax;
150 bool worked = setGroundHeightParent(center, n);
154 next_squares[center + a/2*v2s16(-1,0)] = true;
155 next_squares[center + a/2*v2s16(1,0)] = true;
156 next_squares[center + a/2*v2s16(0,-1)] = true;
157 next_squares[center + a/2*v2s16(0,1)] = true;
162 Adds a point to transform into a square pattern
163 center = The point that is added. The center of a diamond.
164 a = Diameter of the existing diamond. (2, 4, 8, 16, ...)
166 Adds center points of the next diamonds to next_diamonds.
168 void FixedHeightmap::makeSquare(
172 core::map<v2s16, bool> &next_diamonds)
174 /*dstream<<"makeSquare(): center="
175 <<"("<<center.X<<","<<center.Y<<")"
176 <<", a="<<a<<", randmax="<<randmax
177 <<", next_diamonds.size()="<<next_diamonds.size()
180 f32 n = avgNeighbours(center, a/2);
181 // Add (-1.0...1.0) * randmax
182 n += ((float)myrand() / (float)(MYRAND_MAX/2) - 1.0)*randmax;
183 bool worked = setGroundHeightParent(center, n);
187 next_diamonds[center + a/4*v2s16(1,1)] = true;
188 next_diamonds[center + a/4*v2s16(-1,1)] = true;
189 next_diamonds[center + a/4*v2s16(-1,-1)] = true;
190 next_diamonds[center + a/4*v2s16(1,-1)] = true;
194 void FixedHeightmap::DiamondSquare(f32 randmax, f32 randfactor)
202 // Check that a is a power of two
206 core::map<v2s16, bool> next_diamonds;
207 core::map<v2s16, bool> next_squares;
209 next_diamonds[v2s16(a/2, a/2)] = true;
213 next_squares.clear();
215 for(core::map<v2s16, bool>::Iterator
216 i = next_diamonds.getIterator();
217 i.atEnd() == false; i++)
219 v2s16 p = i.getNode()->getKey();
220 makeDiamond(p, a, randmax, next_squares);
225 next_diamonds.clear();
227 for(core::map<v2s16, bool>::Iterator
228 i = next_squares.getIterator();
229 i.atEnd() == false; i++)
231 v2s16 p = i.getNode()->getKey();
232 makeSquare(p, a, randmax, next_diamonds);
238 randmax *= randfactor;
242 void FixedHeightmap::generateContinued(f32 randmax, f32 randfactor,
245 DSTACK(__FUNCTION_NAME);
246 /*dstream<<"FixedHeightmap("<<m_pos_on_master.X
247 <<","<<m_pos_on_master.Y
248 <<")::generateContinued()"<<std::endl;*/
250 // Works only with blocksize=2,4,8,16,32,64,...
253 // Check that a is a power of two
254 assert((a & (a-1)) == 0);
256 // Overwrite with GROUNDHEIGHT_NOTFOUND_SETVALUE
257 for(s16 y=0; y<=a; y++){
258 for(s16 x=0; x<=a; x++){
260 setGroundHeight(p, GROUNDHEIGHT_NOTFOUND_SETVALUE);
265 Fill with corners[] (if not already set)
273 for(u16 i=0; i<4; i++){
274 v2s16 npos = dirs[i] * a;
275 // Don't replace already seeded corners
276 f32 h = getGroundHeight(npos);
277 if(h > GROUNDHEIGHT_VALID_MINVALUE)
279 setGroundHeight(dirs[i] * a, corners[i]);
282 /*dstream<<"corners filled:"<<std::endl;
285 DiamondSquare(randmax, randfactor);
288 u32 FixedHeightmap::serializedLength(u8 version, u16 blocksize)
290 if(!ser_ver_supported(version))
291 throw VersionMismatchException("ERROR: FixedHeightmap format not supported");
295 /*// [0] s32 blocksize
296 // [4] v2s16 pos_on_master
297 // [8] s32 data[W*H] (W=H=blocksize+1)
298 return 4 + 4 + (blocksize+1)*(blocksize+1)*4;*/
300 // [8] s32 data[W*H] (W=H=blocksize+1)
301 return (blocksize+1)*(blocksize+1)*4;
305 u32 FixedHeightmap::serializedLength(u8 version)
307 return serializedLength(version, m_blocksize);
310 void FixedHeightmap::serialize(u8 *dest, u8 version)
312 //dstream<<"FixedHeightmap::serialize"<<std::endl;
314 if(!ser_ver_supported(version))
315 throw VersionMismatchException("ERROR: FixedHeightmap format not supported");
319 /*writeU32(&dest[0], m_blocksize);
320 writeV2S16(&dest[4], m_pos_on_master);
322 for(u32 i=0; i<nodecount; i++)
324 writeS32(&dest[8+i*4], (s32)(m_data[i]*1000.0));
328 for(u32 i=0; i<nodecount; i++)
330 writeS32(&dest[i*4], (s32)(m_data[i]*1000.0));
335 void FixedHeightmap::deSerialize(u8 *source, u8 version)
337 /*dstream<<"FixedHeightmap::deSerialize m_blocksize="
338 <<m_blocksize<<std::endl;*/
340 if(!ser_ver_supported(version))
341 throw VersionMismatchException("ERROR: FixedHeightmap format not supported");
345 u32 nodecount = (m_blocksize+1)*(m_blocksize+1);
346 for(u32 i=0; i<nodecount; i++)
348 m_data[i] = ((f32)readS32(&source[i*4]))/1000.0;
351 /*printf("source[0,1,2,3]=%x,%x,%x,%x\n",
355 (int)source[3]&0xff);
357 dstream<<"m_data[0]="<<m_data[0]<<", "
358 <<"readS32(&source[0])="<<readS32(&source[0])
360 dstream<<"m_data[4*4]="<<m_data[4*4]<<", "
361 <<"readS32(&source[4*4])="<<readS32(&source[4*4])
367 void setcolor(f32 h, f32 rangemin, f32 rangemax)
370 const char *colors[] =
379 u16 colorcount = sizeof(colors)/sizeof(colors[0]);
380 f32 scaled = (h - rangemin) / (rangemax - rangemin);
381 u8 color = scaled * colorcount;
382 if(color > colorcount-1)
383 color = colorcount-1;
384 /*printf("rangemin=%f, rangemax=%f, h=%f -> color=%i\n",
389 printf("%s", colors[color]);
390 //printf("\x1b[31;40m");
391 //printf("\x1b[44;1m");
405 void UnlimitedHeightmap::print()
411 core::map<v2s16, FixedHeightmap*>::Iterator i;
412 i = m_heightmaps.getIterator();
414 printf("UnlimitedHeightmap::print(): empty.\n");
417 for(; i.atEnd() == false; i++)
419 v2s16 p = i.getNode()->getValue()->getPosOnMaster();
420 if(p.X < minx) minx = p.X;
421 if(p.Y < miny) miny = p.Y;
422 if(p.X > maxx) maxx = p.X;
423 if(p.Y > maxy) maxy = p.Y;
425 minx = minx * m_blocksize;
426 miny = miny * m_blocksize;
427 maxx = (maxx+1) * m_blocksize;
428 maxy = (maxy+1) * m_blocksize;
429 printf("UnlimitedHeightmap::print(): from (%i,%i) to (%i,%i)\n",
430 minx, miny, maxx, maxy);
434 f32 rangemax = -1e10;
435 for(s32 y=miny; y<=maxy; y++){
436 for(s32 x=minx; x<=maxx; x++){
437 f32 h = getGroundHeight(v2s16(x,y), false);
438 if(h < GROUNDHEIGHT_VALID_MINVALUE)
448 for(s32 x=minx; x<=maxx; x++){
453 for(s32 y=miny; y<=maxy; y++){
455 for(s32 x=minx; x<=maxx; x++){
456 f32 n = getGroundHeight(v2s16(x,y), false);
457 if(n < GROUNDHEIGHT_VALID_MINVALUE)
461 setcolor(n, rangemin, rangemax);
462 printf("% -5.1f", getGroundHeight(v2s16(x,y), false));
470 FixedHeightmap * UnlimitedHeightmap::getHeightmap(v2s16 p_from, bool generate)
472 DSTACK("UnlimitedHeightmap::getHeightmap()");
474 We want to check that all neighbours of the wanted heightmap
476 This is because generating the neighboring heightmaps will
477 modify the current one.
482 // Go through all neighbors (corners also) and the current one
483 // and generate every one of them.
484 for(s16 x=p_from.X-1; x<=p_from.X+1; x++)
485 for(s16 y=p_from.Y-1; y<=p_from.Y+1; y++)
490 core::map<v2s16, FixedHeightmap*>::Node *n = m_heightmaps.find(p);
497 FixedHeightmap *heightmap = new FixedHeightmap(this, p, m_blocksize);
499 m_heightmaps.insert(p, heightmap);
503 s32 div = SECTOR_HEIGHTMAP_SPLIT * MAP_BLOCKSIZE;
506 PointAttributeList *palist = m_padb->getList("hm_baseheight");
518 corners[0] = palist->getNearAttr((p+v2s16(0,0)) * div).getFloat();
519 corners[1] = palist->getNearAttr((p+v2s16(1,0)) * div).getFloat();
520 corners[2] = palist->getNearAttr((p+v2s16(1,1)) * div).getFloat();
521 corners[3] = palist->getNearAttr((p+v2s16(0,1)) * div).getFloat();
524 corners[0] = palist->getInterpolatedFloat((p+v2s16(0,0))*div);
525 corners[1] = palist->getInterpolatedFloat((p+v2s16(1,0))*div);
526 corners[2] = palist->getInterpolatedFloat((p+v2s16(1,1))*div);
527 corners[3] = palist->getInterpolatedFloat((p+v2s16(0,1))*div);
533 corners[0] = m_base_generator->getValue(p+v2s16(0,0));
534 corners[1] = m_base_generator->getValue(p+v2s16(1,0));
535 corners[2] = m_base_generator->getValue(p+v2s16(1,1));
536 corners[3] = m_base_generator->getValue(p+v2s16(0,1));
539 /*f32 randmax = m_randmax_generator->getValue(p);
540 f32 randfactor = m_randfactor_generator->getValue(p);*/
542 f32 randmax = m_padb->getList("hm_randmax")
543 ->getInterpolatedFloat(p*div);
544 f32 randfactor = m_padb->getList("hm_randfactor")
545 ->getInterpolatedFloat(p*div);
546 //dstream<<"randmax="<<randmax<<" randfactor="<<randfactor<<std::endl;
548 heightmap->generateContinued(randmax, randfactor, corners);
552 core::map<v2s16, FixedHeightmap*>::Node *n = m_heightmaps.find(p_from);
556 return n->getValue();
560 throw InvalidPositionException
561 ("Something went really wrong in UnlimitedHeightmap::getHeightmap");
565 f32 UnlimitedHeightmap::getGroundHeight(v2s16 p, bool generate)
567 v2s16 heightmappos = getNodeHeightmapPos(p);
568 v2s16 relpos = p - heightmappos*m_blocksize;
570 FixedHeightmap * href = getHeightmap(heightmappos, generate);
571 f32 h = href->getGroundHeight(relpos);
572 if(h > GROUNDHEIGHT_VALID_MINVALUE)
575 catch(InvalidPositionException){}
577 If on border or in the (0,0) corner, try to get from
578 overlapping heightmaps
582 FixedHeightmap * href = getHeightmap(
583 heightmappos-v2s16(1,0), false);
584 f32 h = href->getGroundHeight(v2s16(m_blocksize, relpos.Y));
585 if(h > GROUNDHEIGHT_VALID_MINVALUE)
588 catch(InvalidPositionException){}
592 FixedHeightmap * href = getHeightmap(
593 heightmappos-v2s16(0,1), false);
594 f32 h = href->getGroundHeight(v2s16(relpos.X, m_blocksize));
595 if(h > GROUNDHEIGHT_VALID_MINVALUE)
598 catch(InvalidPositionException){}
600 if(relpos.X == 0 && relpos.Y == 0){
602 FixedHeightmap * href = getHeightmap(
603 heightmappos-v2s16(1,1), false);
604 f32 h = href->getGroundHeight(v2s16(m_blocksize, m_blocksize));
605 if(h > GROUNDHEIGHT_VALID_MINVALUE)
608 catch(InvalidPositionException){}
610 return GROUNDHEIGHT_NOTFOUND_SETVALUE;
613 void UnlimitedHeightmap::setGroundHeight(v2s16 p, f32 y, bool generate)
615 bool was_set = false;
617 v2s16 heightmappos = getNodeHeightmapPos(p);
618 v2s16 relpos = p - heightmappos*m_blocksize;
619 /*dstream<<"UnlimitedHeightmap::setGroundHeight(("
620 <<p.X<<","<<p.Y<<"), "<<y<<"): "
621 <<"heightmappos=("<<heightmappos.X<<","
622 <<heightmappos.Y<<") relpos=("
623 <<relpos.X<<","<<relpos.Y<<")"
626 FixedHeightmap * href = getHeightmap(heightmappos, generate);
627 href->setGroundHeight(relpos, y);
629 }catch(InvalidPositionException){}
630 // Update in neighbour heightmap if it's at border
633 FixedHeightmap * href = getHeightmap(
634 heightmappos-v2s16(1,0), generate);
635 href->setGroundHeight(v2s16(m_blocksize, relpos.Y), y);
637 }catch(InvalidPositionException){}
641 FixedHeightmap * href = getHeightmap(
642 heightmappos-v2s16(0,1), generate);
643 href->setGroundHeight(v2s16(relpos.X, m_blocksize), y);
645 }catch(InvalidPositionException){}
647 if(relpos.X == 0 && relpos.Y == 0){
649 FixedHeightmap * href = getHeightmap(
650 heightmappos-v2s16(1,1), generate);
651 href->setGroundHeight(v2s16(m_blocksize, m_blocksize), y);
653 }catch(InvalidPositionException){}
658 throw InvalidPositionException
659 ("UnlimitedHeightmap failed to set height");
664 void UnlimitedHeightmap::serialize(std::ostream &os, u8 version)
666 //dstream<<"UnlimitedHeightmap::serialize()"<<std::endl;
668 if(!ser_ver_supported(version))
669 throw VersionMismatchException
670 ("ERROR: UnlimitedHeightmap format not supported");
674 /*if(m_base_generator->getId() != VALUE_GENERATOR_ID_CONSTANT
675 || m_randmax_generator->getId() != VALUE_GENERATOR_ID_CONSTANT
676 || m_randfactor_generator->getId() != VALUE_GENERATOR_ID_CONSTANT)*/
677 /*if(std::string(m_base_generator->getName()) != "constant"
678 || std::string(m_randmax_generator->getName()) != "constant"
679 || std::string(m_randfactor_generator->getName()) != "constant")
681 throw SerializationError
682 ("Cannot write UnlimitedHeightmap in old version: "
683 "Generators are not ConstantGenerators.");
689 f32 randfactor = 0.0;
692 os.write((char*)&version, 1);
697 [6] s32 randfactor*1000
698 [10] s32 basevalue*1000
699 [14] u32 heightmap_count
700 [18] X * (v2s16 pos + heightmap)
703 FixedHeightmap::serializedLength(version, m_blocksize);
704 u32 heightmap_count = m_heightmaps.size();
706 //dstream<<"heightmap_size="<<heightmap_size<<std::endl;
708 u32 datasize = 2+4+4+4+4+heightmap_count*(4+heightmap_size);
709 SharedBuffer<u8> data(datasize);
711 writeU16(&data[0], m_blocksize);
712 writeU32(&data[2], (s32)(randmax*1000.0));
713 writeU32(&data[6], (s32)(randfactor*1000.0));
714 writeU32(&data[10], (s32)(basevalue*1000.0));
715 writeU32(&data[14], heightmap_count);
717 core::map<v2s16, FixedHeightmap*>::Iterator j;
718 j = m_heightmaps.getIterator();
720 for(; j.atEnd() == false; j++)
722 FixedHeightmap *hm = j.getNode()->getValue();
723 v2s16 pos = j.getNode()->getKey();
724 writeV2S16(&data[18+i*(4+heightmap_size)], pos);
725 hm->serialize(&data[18+i*(4+heightmap_size)+4], version);
729 os.write((char*)*data, data.getSize());
731 else if(version <= 11)
734 os.write((char*)&version, 1);
738 writeU16(buf, m_blocksize);
739 os.write((char*)buf, 2);
741 /*m_randmax_generator->serialize(os);
742 m_randfactor_generator->serialize(os);
743 m_base_generator->serialize(os);*/
744 os<<"constant 0.0\n";
745 os<<"constant 0.0\n";
746 os<<"constant 0.0\n";
748 u32 heightmap_count = m_heightmaps.size();
749 writeU32(buf, heightmap_count);
750 os.write((char*)buf, 4);
753 FixedHeightmap::serializedLength(version, m_blocksize);
755 SharedBuffer<u8> hmdata(heightmap_size);
757 core::map<v2s16, FixedHeightmap*>::Iterator j;
758 j = m_heightmaps.getIterator();
760 for(; j.atEnd() == false; j++)
762 v2s16 pos = j.getNode()->getKey();
763 writeV2S16(buf, pos);
764 os.write((char*)buf, 4);
766 FixedHeightmap *hm = j.getNode()->getValue();
767 hm->serialize(*hmdata, version);
768 os.write((char*)*hmdata, hmdata.getSize());
776 os.write((char*)&version, 1);
780 writeU16(buf, m_blocksize);
781 os.write((char*)buf, 2);
783 /*m_randmax_generator->serialize(os);
784 m_randfactor_generator->serialize(os);
785 m_base_generator->serialize(os);*/
787 u32 heightmap_count = m_heightmaps.size();
788 writeU32(buf, heightmap_count);
789 os.write((char*)buf, 4);
792 FixedHeightmap::serializedLength(version, m_blocksize);
794 SharedBuffer<u8> hmdata(heightmap_size);
796 core::map<v2s16, FixedHeightmap*>::Iterator j;
797 j = m_heightmaps.getIterator();
799 for(; j.atEnd() == false; j++)
801 v2s16 pos = j.getNode()->getKey();
802 writeV2S16(buf, pos);
803 os.write((char*)buf, 4);
805 FixedHeightmap *hm = j.getNode()->getValue();
806 hm->serialize(*hmdata, version);
807 os.write((char*)*hmdata, hmdata.getSize());
816 /*if(m_base_generator->getId() != VALUE_GENERATOR_ID_CONSTANT
817 || m_randmax_generator->getId() != VALUE_GENERATOR_ID_CONSTANT
818 || m_randfactor_generator->getId() != VALUE_GENERATOR_ID_CONSTANT)*/
819 if(std::string(m_base_generator->getName()) != "constant"
820 || std::string(m_randmax_generator->getName()) != "constant"
821 || std::string(m_randfactor_generator->getName()) != "constant")
823 throw SerializationError
824 ("Cannot write UnlimitedHeightmap in old version: "
825 "Generators are not ConstantGenerators.");
828 f32 basevalue = ((ConstantGenerator*)m_base_generator)->m_value;
829 f32 randmax = ((ConstantGenerator*)m_randmax_generator)->m_value;
830 f32 randfactor = ((ConstantGenerator*)m_randfactor_generator)->m_value;
833 os.write((char*)&version, 1);
838 [6] s32 randfactor*1000
839 [10] s32 basevalue*1000
840 [14] u32 heightmap_count
841 [18] X * (v2s16 pos + heightmap)
844 FixedHeightmap::serializedLength(version, m_blocksize);
845 u32 heightmap_count = m_heightmaps.size();
847 //dstream<<"heightmap_size="<<heightmap_size<<std::endl;
849 u32 datasize = 2+4+4+4+4+heightmap_count*(4+heightmap_size);
850 SharedBuffer<u8> data(datasize);
852 writeU16(&data[0], m_blocksize);
853 writeU32(&data[2], (s32)(randmax*1000.0));
854 writeU32(&data[6], (s32)(randfactor*1000.0));
855 writeU32(&data[10], (s32)(basevalue*1000.0));
856 writeU32(&data[14], heightmap_count);
858 core::map<v2s16, FixedHeightmap*>::Iterator j;
859 j = m_heightmaps.getIterator();
861 for(; j.atEnd() == false; j++)
863 FixedHeightmap *hm = j.getNode()->getValue();
864 v2s16 pos = j.getNode()->getKey();
865 writeV2S16(&data[18+i*(4+heightmap_size)], pos);
866 hm->serialize(&data[18+i*(4+heightmap_size)+4], version);
870 os.write((char*)*data, data.getSize());
875 os.write((char*)&version, 1);
879 writeU16(buf, m_blocksize);
880 os.write((char*)buf, 2);
882 /*m_randmax_generator->serialize(os, version);
883 m_randfactor_generator->serialize(os, version);
884 m_base_generator->serialize(os, version);*/
885 m_randmax_generator->serialize(os);
886 m_randfactor_generator->serialize(os);
887 m_base_generator->serialize(os);
889 u32 heightmap_count = m_heightmaps.size();
890 writeU32(buf, heightmap_count);
891 os.write((char*)buf, 4);
894 FixedHeightmap::serializedLength(version, m_blocksize);
896 SharedBuffer<u8> hmdata(heightmap_size);
898 core::map<v2s16, FixedHeightmap*>::Iterator j;
899 j = m_heightmaps.getIterator();
901 for(; j.atEnd() == false; j++)
903 v2s16 pos = j.getNode()->getKey();
904 writeV2S16(buf, pos);
905 os.write((char*)buf, 4);
907 FixedHeightmap *hm = j.getNode()->getValue();
908 hm->serialize(*hmdata, version);
909 os.write((char*)*hmdata, hmdata.getSize());
917 UnlimitedHeightmap * UnlimitedHeightmap::deSerialize(std::istream &is,
918 PointAttributeDatabase *padb)
921 is.read((char*)&version, 1);
923 if(!ser_ver_supported(version))
924 throw VersionMismatchException("ERROR: UnlimitedHeightmap format not supported");
931 [6] s32 randfactor*1000
932 [10] s32 basevalue*1000
933 [14] u32 heightmap_count
934 [18] X * (v2s16 pos + heightmap)
936 SharedBuffer<u8> data(18);
937 is.read((char*)*data, 18);
938 if(is.gcount() != 18)
939 throw SerializationError
940 ("UnlimitedHeightmap::deSerialize: no enough input data");
941 s16 blocksize = readU16(&data[0]);
942 // Dummy read randmax, randfactor, basevalue
943 /*f32 randmax = (f32)*/readU32(&data[2]) /*/ 1000.0*/;
944 /*f32 randfactor = (f32)*/readU32(&data[6]) /*/ 1000.0*/;
945 /*f32 basevalue = (f32)*/readU32(&data[10]) /*/ 1000.0*/;
946 u32 heightmap_count = readU32(&data[14]);
948 /*dstream<<"UnlimitedHeightmap::deSerialize():"
949 <<" blocksize="<<blocksize
950 <<" heightmap_count="<<heightmap_count
954 FixedHeightmap::serializedLength(version, blocksize);
956 //dstream<<"heightmap_size="<<heightmap_size<<std::endl;
958 /*ValueGenerator *maxgen = new ConstantGenerator(randmax);
959 ValueGenerator *factorgen = new ConstantGenerator(randfactor);
960 ValueGenerator *basegen = new ConstantGenerator(basevalue);*/
962 UnlimitedHeightmap *hm = new UnlimitedHeightmap
965 for(u32 i=0; i<heightmap_count; i++)
967 //dstream<<"i="<<i<<std::endl;
968 SharedBuffer<u8> data(4+heightmap_size);
969 is.read((char*)*data, 4+heightmap_size);
970 if(is.gcount() != (s32)(4+heightmap_size)){
972 throw SerializationError
973 ("UnlimitedHeightmap::deSerialize: no enough input data");
975 v2s16 pos = readV2S16(&data[0]);
976 FixedHeightmap *f = new FixedHeightmap(hm, pos, blocksize);
977 f->deSerialize(&data[4], version);
978 hm->m_heightmaps.insert(pos, f);
982 else if(version <= 11)
986 is.read((char*)buf, 2);
987 s16 blocksize = readU16(buf);
989 // Dummy-read three lines (generators)
990 std::string templine;
991 std::getline(is, templine, '\n');
993 is.read((char*)buf, 4);
994 u32 heightmap_count = readU32(buf);
997 FixedHeightmap::serializedLength(version, blocksize);
999 UnlimitedHeightmap *hm = new UnlimitedHeightmap
1002 for(u32 i=0; i<heightmap_count; i++)
1004 is.read((char*)buf, 4);
1005 v2s16 pos = readV2S16(buf);
1007 SharedBuffer<u8> data(heightmap_size);
1008 is.read((char*)*data, heightmap_size);
1009 if(is.gcount() != (s32)(heightmap_size)){
1011 throw SerializationError
1012 ("UnlimitedHeightmap::deSerialize: no enough input data");
1014 FixedHeightmap *f = new FixedHeightmap(hm, pos, blocksize);
1015 f->deSerialize(*data, version);
1016 hm->m_heightmaps.insert(pos, f);
1024 is.read((char*)buf, 2);
1025 s16 blocksize = readU16(buf);
1027 /*ValueGenerator *maxgen = ValueGenerator::deSerialize(is);
1028 ValueGenerator *factorgen = ValueGenerator::deSerialize(is);
1029 ValueGenerator *basegen = ValueGenerator::deSerialize(is);*/
1031 is.read((char*)buf, 4);
1032 u32 heightmap_count = readU32(buf);
1034 u32 heightmap_size =
1035 FixedHeightmap::serializedLength(version, blocksize);
1037 UnlimitedHeightmap *hm = new UnlimitedHeightmap
1040 for(u32 i=0; i<heightmap_count; i++)
1042 is.read((char*)buf, 4);
1043 v2s16 pos = readV2S16(buf);
1045 SharedBuffer<u8> data(heightmap_size);
1046 is.read((char*)*data, heightmap_size);
1047 if(is.gcount() != (s32)(heightmap_size)){
1049 throw SerializationError
1050 ("UnlimitedHeightmap::deSerialize: no enough input data");
1052 FixedHeightmap *f = new FixedHeightmap(hm, pos, blocksize);
1053 f->deSerialize(*data, version);
1054 hm->m_heightmaps.insert(pos, f);