diff options
Diffstat (limited to 'src/heightmap.cpp')
-rw-r--r-- | src/heightmap.cpp | 1060 |
1 files changed, 0 insertions, 1060 deletions
diff --git a/src/heightmap.cpp b/src/heightmap.cpp deleted file mode 100644 index bb7f2a1d1..000000000 --- a/src/heightmap.cpp +++ /dev/null @@ -1,1060 +0,0 @@ -/* -Minetest-c55 -Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com> - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -/* -(c) 2010 Perttu Ahola <celeron55@gmail.com> -*/ - -#include "heightmap.h" - -// For MAP_BLOCKSIZE -#include "mapblock.h" - -/* - ValueGenerator -*/ - -ValueGenerator* ValueGenerator::deSerialize(std::string line) -{ - std::istringstream ss(line); - //ss.imbue(std::locale("C")); - - std::string name; - std::getline(ss, name, ' '); - - if(name == "constant") - { - f32 value; - ss>>value; - - return new ConstantGenerator(value); - } - else if(name == "linear") - { - f32 height; - v2f slope; - - ss>>height; - ss>>slope.X; - ss>>slope.Y; - - return new LinearGenerator(height, slope); - } - else if(name == "power") - { - f32 height; - v2f slope; - f32 power; - - ss>>height; - ss>>slope.X; - ss>>slope.Y; - ss>>power; - - return new PowerGenerator(height, slope, power); - } - else - { - throw SerializationError - ("Invalid heightmap generator (deSerialize)"); - } -} - -/* - FixedHeightmap -*/ - -f32 FixedHeightmap::avgNeighbours(v2s16 p, s16 d) -{ - v2s16 dirs[4] = { - v2s16(1,0), - v2s16(0,1), - v2s16(-1,0), - v2s16(0,-1) - }; - f32 sum = 0.0; - f32 count = 0.0; - for(u16 i=0; i<4; i++){ - v2s16 p2 = p + dirs[i] * d; - f32 n = getGroundHeightParent(p2); - if(n < GROUNDHEIGHT_VALID_MINVALUE) - continue; - sum += n; - count += 1.0; - } - assert(count > 0.001); - return sum / count; -} - -f32 FixedHeightmap::avgDiagNeighbours(v2s16 p, s16 d) -{ - v2s16 dirs[4] = { - v2s16(1,1), - v2s16(-1,-1), - v2s16(-1,1), - v2s16(1,-1) - }; - f32 sum = 0.0; - f32 count = 0.0; - for(u16 i=0; i<4; i++){ - v2s16 p2 = p + dirs[i] * d; - f32 n = getGroundHeightParent(p2); - if(n < GROUNDHEIGHT_VALID_MINVALUE) - continue; - sum += n; - count += 1.0; - } - assert(count > 0.001); - return sum / count; -} - -/* - Adds a point to transform into a diamond pattern - center = Center of the diamond phase (center of a square) - a = Side length of the existing square (2, 4, 8, ...) - - Adds the center points of the next squares to next_squares as - dummy "true" values. -*/ -void FixedHeightmap::makeDiamond( - v2s16 center, - s16 a, - f32 randmax, - core::map<v2s16, bool> &next_squares) -{ - /*dstream<<"makeDiamond(): center=" - <<"("<<center.X<<","<<center.Y<<")" - <<", a="<<a<<", randmax="<<randmax - <<", next_squares.size()="<<next_squares.size() - <<std::endl;*/ - - f32 n = avgDiagNeighbours(center, a/2); - // Add (-1.0...1.0) * randmax - n += ((float)myrand() / (float)(MYRAND_MAX/2) - 1.0)*randmax; - bool worked = setGroundHeightParent(center, n); - - if(a >= 2 && worked) - { - next_squares[center + a/2*v2s16(-1,0)] = true; - next_squares[center + a/2*v2s16(1,0)] = true; - next_squares[center + a/2*v2s16(0,-1)] = true; - next_squares[center + a/2*v2s16(0,1)] = true; - } -} - -/* - Adds a point to transform into a square pattern - center = The point that is added. The center of a diamond. - a = Diameter of the existing diamond. (2, 4, 8, 16, ...) - - Adds center points of the next diamonds to next_diamonds. -*/ -void FixedHeightmap::makeSquare( - v2s16 center, - s16 a, - f32 randmax, - core::map<v2s16, bool> &next_diamonds) -{ - /*dstream<<"makeSquare(): center=" - <<"("<<center.X<<","<<center.Y<<")" - <<", a="<<a<<", randmax="<<randmax - <<", next_diamonds.size()="<<next_diamonds.size() - <<std::endl;*/ - - f32 n = avgNeighbours(center, a/2); - // Add (-1.0...1.0) * randmax - n += ((float)myrand() / (float)(MYRAND_MAX/2) - 1.0)*randmax; - bool worked = setGroundHeightParent(center, n); - - if(a >= 4 && worked) - { - next_diamonds[center + a/4*v2s16(1,1)] = true; - next_diamonds[center + a/4*v2s16(-1,1)] = true; - next_diamonds[center + a/4*v2s16(-1,-1)] = true; - next_diamonds[center + a/4*v2s16(1,-1)] = true; - } -} - -void FixedHeightmap::DiamondSquare(f32 randmax, f32 randfactor) -{ - u16 a; - if(W < H) - a = W-1; - else - a = H-1; - - // Check that a is a power of two - if((a & (a-1)) != 0) - throw; - - core::map<v2s16, bool> next_diamonds; - core::map<v2s16, bool> next_squares; - - next_diamonds[v2s16(a/2, a/2)] = true; - - while(a >= 2) - { - next_squares.clear(); - - for(core::map<v2s16, bool>::Iterator - i = next_diamonds.getIterator(); - i.atEnd() == false; i++) - { - v2s16 p = i.getNode()->getKey(); - makeDiamond(p, a, randmax, next_squares); - } - - //print(); - - next_diamonds.clear(); - - for(core::map<v2s16, bool>::Iterator - i = next_squares.getIterator(); - i.atEnd() == false; i++) - { - v2s16 p = i.getNode()->getKey(); - makeSquare(p, a, randmax, next_diamonds); - } - - //print(); - - a /= 2; - randmax *= randfactor; - } -} - -void FixedHeightmap::generateContinued(f32 randmax, f32 randfactor, - f32 *corners) -{ - DSTACK(__FUNCTION_NAME); - /*dstream<<"FixedHeightmap("<<m_pos_on_master.X - <<","<<m_pos_on_master.Y - <<")::generateContinued()"<<std::endl;*/ - - // Works only with blocksize=2,4,8,16,32,64,... - s16 a = m_blocksize; - - // Check that a is a power of two - assert((a & (a-1)) == 0); - - // Overwrite with GROUNDHEIGHT_NOTFOUND_SETVALUE - for(s16 y=0; y<=a; y++){ - for(s16 x=0; x<=a; x++){ - v2s16 p(x,y); - setGroundHeight(p, GROUNDHEIGHT_NOTFOUND_SETVALUE); - } - } - - /* - Fill with corners[] (if not already set) - */ - v2s16 dirs[4] = { - v2s16(0,0), - v2s16(1,0), - v2s16(1,1), - v2s16(0,1), - }; - for(u16 i=0; i<4; i++){ - v2s16 npos = dirs[i] * a; - // Don't replace already seeded corners - f32 h = getGroundHeight(npos); - if(h > GROUNDHEIGHT_VALID_MINVALUE) - continue; - setGroundHeight(dirs[i] * a, corners[i]); - } - - /*dstream<<"corners filled:"<<std::endl; - print();*/ - - DiamondSquare(randmax, randfactor); -} - -u32 FixedHeightmap::serializedLength(u8 version, u16 blocksize) -{ - if(!ser_ver_supported(version)) - throw VersionMismatchException("ERROR: FixedHeightmap format not supported"); - - // Any version - { - /*// [0] s32 blocksize - // [4] v2s16 pos_on_master - // [8] s32 data[W*H] (W=H=blocksize+1) - return 4 + 4 + (blocksize+1)*(blocksize+1)*4;*/ - - // [8] s32 data[W*H] (W=H=blocksize+1) - return (blocksize+1)*(blocksize+1)*4; - } -} - -u32 FixedHeightmap::serializedLength(u8 version) -{ - return serializedLength(version, m_blocksize); -} - -void FixedHeightmap::serialize(u8 *dest, u8 version) -{ - //dstream<<"FixedHeightmap::serialize"<<std::endl; - - if(!ser_ver_supported(version)) - throw VersionMismatchException("ERROR: FixedHeightmap format not supported"); - - // Any version - { - /*writeU32(&dest[0], m_blocksize); - writeV2S16(&dest[4], m_pos_on_master); - u32 nodecount = W*H; - for(u32 i=0; i<nodecount; i++) - { - writeS32(&dest[8+i*4], (s32)(m_data[i]*1000.0)); - }*/ - - u32 nodecount = W*H; - for(u32 i=0; i<nodecount; i++) - { - writeS32(&dest[i*4], (s32)(m_data[i]*1000.0)); - } - } -} - -void FixedHeightmap::deSerialize(u8 *source, u8 version) -{ - /*dstream<<"FixedHeightmap::deSerialize m_blocksize=" - <<m_blocksize<<std::endl;*/ - - if(!ser_ver_supported(version)) - throw VersionMismatchException("ERROR: FixedHeightmap format not supported"); - - // Any version - { - u32 nodecount = (m_blocksize+1)*(m_blocksize+1); - for(u32 i=0; i<nodecount; i++) - { - m_data[i] = ((f32)readS32(&source[i*4]))/1000.0; - } - - /*printf("source[0,1,2,3]=%x,%x,%x,%x\n", - (int)source[0]&0xff, - (int)source[1]&0xff, - (int)source[2]&0xff, - (int)source[3]&0xff); - - dstream<<"m_data[0]="<<m_data[0]<<", " - <<"readS32(&source[0])="<<readS32(&source[0]) - <<std::endl; - dstream<<"m_data[4*4]="<<m_data[4*4]<<", " - <<"readS32(&source[4*4])="<<readS32(&source[4*4]) - <<std::endl;*/ - } -} - - -void setcolor(f32 h, f32 rangemin, f32 rangemax) -{ -#ifndef _WIN32 - const char *colors[] = - { - "\x1b[40m", - "\x1b[44m", - "\x1b[46m", - "\x1b[42m", - "\x1b[43m", - "\x1b[41m", - }; - u16 colorcount = sizeof(colors)/sizeof(colors[0]); - f32 scaled = (h - rangemin) / (rangemax - rangemin); - u8 color = scaled * colorcount; - if(color > colorcount-1) - color = colorcount-1; - /*printf("rangemin=%f, rangemax=%f, h=%f -> color=%i\n", - rangemin, - rangemax, - h, - color);*/ - printf("%s", colors[color]); - //printf("\x1b[31;40m"); - //printf("\x1b[44;1m"); -#endif -} -void resetcolor() -{ -#ifndef _WIN32 - printf("\x1b[0m"); -#endif -} - -/* - UnlimitedHeightmap -*/ - -void UnlimitedHeightmap::print() -{ - s16 minx = 10000; - s16 miny = 10000; - s16 maxx = -10000; - s16 maxy = -10000; - core::map<v2s16, FixedHeightmap*>::Iterator i; - i = m_heightmaps.getIterator(); - if(i.atEnd()){ - printf("UnlimitedHeightmap::print(): empty.\n"); - return; - } - for(; i.atEnd() == false; i++) - { - v2s16 p = i.getNode()->getValue()->getPosOnMaster(); - if(p.X < minx) minx = p.X; - if(p.Y < miny) miny = p.Y; - if(p.X > maxx) maxx = p.X; - if(p.Y > maxy) maxy = p.Y; - } - minx = minx * m_blocksize; - miny = miny * m_blocksize; - maxx = (maxx+1) * m_blocksize; - maxy = (maxy+1) * m_blocksize; - printf("UnlimitedHeightmap::print(): from (%i,%i) to (%i,%i)\n", - minx, miny, maxx, maxy); - - // Calculate range - f32 rangemin = 1e10; - f32 rangemax = -1e10; - for(s32 y=miny; y<=maxy; y++){ - for(s32 x=minx; x<=maxx; x++){ - f32 h = getGroundHeight(v2s16(x,y), false); - if(h < GROUNDHEIGHT_VALID_MINVALUE) - continue; - if(h < rangemin) - rangemin = h; - if(h > rangemax) - rangemax = h; - } - } - - printf(" "); - for(s32 x=minx; x<=maxx; x++){ - printf("% .3d ", x); - } - printf("\n"); - - for(s32 y=miny; y<=maxy; y++){ - printf("% .3d ", y); - for(s32 x=minx; x<=maxx; x++){ - f32 n = getGroundHeight(v2s16(x,y), false); - if(n < GROUNDHEIGHT_VALID_MINVALUE) - printf(" - "); - else - { - setcolor(n, rangemin, rangemax); - printf("% -5.1f", getGroundHeight(v2s16(x,y), false)); - resetcolor(); - } - } - printf("\n"); - } -} - -FixedHeightmap * UnlimitedHeightmap::getHeightmap(v2s16 p_from, bool generate) -{ - DSTACK("UnlimitedHeightmap::getHeightmap()"); - /* - We want to check that all neighbours of the wanted heightmap - exist. - This is because generating the neighboring heightmaps will - modify the current one. - */ - - if(generate) - { - // Go through all neighbors (corners also) and the current one - // and generate every one of them. - for(s16 x=p_from.X-1; x<=p_from.X+1; x++) - for(s16 y=p_from.Y-1; y<=p_from.Y+1; y++) - { - v2s16 p(x,y); - - // Check if exists - core::map<v2s16, FixedHeightmap*>::Node *n = m_heightmaps.find(p); - if(n != NULL) - continue; - - // Doesn't exist - // Generate it - - FixedHeightmap *heightmap = new FixedHeightmap(this, p, m_blocksize); - - m_heightmaps.insert(p, heightmap); - - f32 corners[4]; - - s32 div = SECTOR_HEIGHTMAP_SPLIT * MAP_BLOCKSIZE; - - { - PointAttributeList *palist = m_padb->getList("hm_baseheight"); - - if(palist->empty()) - { - corners[0] = 0; - corners[1] = 0; - corners[2] = 0; - corners[3] = 0; - } - else - { -#if 0 - corners[0] = palist->getNearAttr((p+v2s16(0,0)) * div).getFloat(); - corners[1] = palist->getNearAttr((p+v2s16(1,0)) * div).getFloat(); - corners[2] = palist->getNearAttr((p+v2s16(1,1)) * div).getFloat(); - corners[3] = palist->getNearAttr((p+v2s16(0,1)) * div).getFloat(); -#endif -#if 1 - corners[0] = palist->getInterpolatedFloat((p+v2s16(0,0))*div); - corners[1] = palist->getInterpolatedFloat((p+v2s16(1,0))*div); - corners[2] = palist->getInterpolatedFloat((p+v2s16(1,1))*div); - corners[3] = palist->getInterpolatedFloat((p+v2s16(0,1))*div); -#endif - } - } - /*else - { - corners[0] = m_base_generator->getValue(p+v2s16(0,0)); - corners[1] = m_base_generator->getValue(p+v2s16(1,0)); - corners[2] = m_base_generator->getValue(p+v2s16(1,1)); - corners[3] = m_base_generator->getValue(p+v2s16(0,1)); - }*/ - - /*f32 randmax = m_randmax_generator->getValue(p); - f32 randfactor = m_randfactor_generator->getValue(p);*/ - - f32 randmax = m_padb->getList("hm_randmax") - ->getInterpolatedFloat(p*div); - f32 randfactor = m_padb->getList("hm_randfactor") - ->getInterpolatedFloat(p*div); - //dstream<<"randmax="<<randmax<<" randfactor="<<randfactor<<std::endl; - - heightmap->generateContinued(randmax, randfactor, corners); - } - } - - core::map<v2s16, FixedHeightmap*>::Node *n = m_heightmaps.find(p_from); - - if(n != NULL) - { - return n->getValue(); - } - else - { - throw InvalidPositionException - ("Something went really wrong in UnlimitedHeightmap::getHeightmap"); - } -} - -f32 UnlimitedHeightmap::getGroundHeight(v2s16 p, bool generate) -{ - v2s16 heightmappos = getNodeHeightmapPos(p); - v2s16 relpos = p - heightmappos*m_blocksize; - try{ - FixedHeightmap * href = getHeightmap(heightmappos, generate); - f32 h = href->getGroundHeight(relpos); - if(h > GROUNDHEIGHT_VALID_MINVALUE) - return h; - } - catch(InvalidPositionException){} - /* - If on border or in the (0,0) corner, try to get from - overlapping heightmaps - */ - if(relpos.X == 0){ - try{ - FixedHeightmap * href = getHeightmap( - heightmappos-v2s16(1,0), false); - f32 h = href->getGroundHeight(v2s16(m_blocksize, relpos.Y)); - if(h > GROUNDHEIGHT_VALID_MINVALUE) - return h; - } - catch(InvalidPositionException){} - } - if(relpos.Y == 0){ - try{ - FixedHeightmap * href = getHeightmap( - heightmappos-v2s16(0,1), false); - f32 h = href->getGroundHeight(v2s16(relpos.X, m_blocksize)); - if(h > GROUNDHEIGHT_VALID_MINVALUE) - return h; - } - catch(InvalidPositionException){} - } - if(relpos.X == 0 && relpos.Y == 0){ - try{ - FixedHeightmap * href = getHeightmap( - heightmappos-v2s16(1,1), false); - f32 h = href->getGroundHeight(v2s16(m_blocksize, m_blocksize)); - if(h > GROUNDHEIGHT_VALID_MINVALUE) - return h; - } - catch(InvalidPositionException){} - } - return GROUNDHEIGHT_NOTFOUND_SETVALUE; -} - -void UnlimitedHeightmap::setGroundHeight(v2s16 p, f32 y, bool generate) -{ - bool was_set = false; - - v2s16 heightmappos = getNodeHeightmapPos(p); - v2s16 relpos = p - heightmappos*m_blocksize; - /*dstream<<"UnlimitedHeightmap::setGroundHeight((" - <<p.X<<","<<p.Y<<"), "<<y<<"): " - <<"heightmappos=("<<heightmappos.X<<"," - <<heightmappos.Y<<") relpos=(" - <<relpos.X<<","<<relpos.Y<<")" - <<std::endl;*/ - try{ - FixedHeightmap * href = getHeightmap(heightmappos, generate); - href->setGroundHeight(relpos, y); - was_set = true; - }catch(InvalidPositionException){} - // Update in neighbour heightmap if it's at border - if(relpos.X == 0){ - try{ - FixedHeightmap * href = getHeightmap( - heightmappos-v2s16(1,0), generate); - href->setGroundHeight(v2s16(m_blocksize, relpos.Y), y); - was_set = true; - }catch(InvalidPositionException){} - } - if(relpos.Y == 0){ - try{ - FixedHeightmap * href = getHeightmap( - heightmappos-v2s16(0,1), generate); - href->setGroundHeight(v2s16(relpos.X, m_blocksize), y); - was_set = true; - }catch(InvalidPositionException){} - } - if(relpos.X == 0 && relpos.Y == 0){ - try{ - FixedHeightmap * href = getHeightmap( - heightmappos-v2s16(1,1), generate); - href->setGroundHeight(v2s16(m_blocksize, m_blocksize), y); - was_set = true; - }catch(InvalidPositionException){} - } - - if(was_set == false) - { - throw InvalidPositionException - ("UnlimitedHeightmap failed to set height"); - } -} - - -void UnlimitedHeightmap::serialize(std::ostream &os, u8 version) -{ - //dstream<<"UnlimitedHeightmap::serialize()"<<std::endl; - - if(!ser_ver_supported(version)) - throw VersionMismatchException - ("ERROR: UnlimitedHeightmap format not supported"); - - if(version <= 7) - { - /*if(m_base_generator->getId() != VALUE_GENERATOR_ID_CONSTANT - || m_randmax_generator->getId() != VALUE_GENERATOR_ID_CONSTANT - || m_randfactor_generator->getId() != VALUE_GENERATOR_ID_CONSTANT)*/ - /*if(std::string(m_base_generator->getName()) != "constant" - || std::string(m_randmax_generator->getName()) != "constant" - || std::string(m_randfactor_generator->getName()) != "constant") - { - throw SerializationError - ("Cannot write UnlimitedHeightmap in old version: " - "Generators are not ConstantGenerators."); - }*/ - - // Dummy values - f32 basevalue = 0.0; - f32 randmax = 0.0; - f32 randfactor = 0.0; - - // Write version - os.write((char*)&version, 1); - - /* - [0] u16 blocksize - [2] s32 randmax*1000 - [6] s32 randfactor*1000 - [10] s32 basevalue*1000 - [14] u32 heightmap_count - [18] X * (v2s16 pos + heightmap) - */ - u32 heightmap_size = - FixedHeightmap::serializedLength(version, m_blocksize); - u32 heightmap_count = m_heightmaps.size(); - - //dstream<<"heightmap_size="<<heightmap_size<<std::endl; - - u32 datasize = 2+4+4+4+4+heightmap_count*(4+heightmap_size); - SharedBuffer<u8> data(datasize); - - writeU16(&data[0], m_blocksize); - writeU32(&data[2], (s32)(randmax*1000.0)); - writeU32(&data[6], (s32)(randfactor*1000.0)); - writeU32(&data[10], (s32)(basevalue*1000.0)); - writeU32(&data[14], heightmap_count); - - core::map<v2s16, FixedHeightmap*>::Iterator j; - j = m_heightmaps.getIterator(); - u32 i=0; - for(; j.atEnd() == false; j++) - { - FixedHeightmap *hm = j.getNode()->getValue(); - v2s16 pos = j.getNode()->getKey(); - writeV2S16(&data[18+i*(4+heightmap_size)], pos); - hm->serialize(&data[18+i*(4+heightmap_size)+4], version); - i++; - } - - os.write((char*)*data, data.getSize()); - } - else if(version <= 11) - { - // Write version - os.write((char*)&version, 1); - - u8 buf[4]; - - writeU16(buf, m_blocksize); - os.write((char*)buf, 2); - - /*m_randmax_generator->serialize(os); - m_randfactor_generator->serialize(os); - m_base_generator->serialize(os);*/ - os<<"constant 0.0\n"; - os<<"constant 0.0\n"; - os<<"constant 0.0\n"; - - u32 heightmap_count = m_heightmaps.size(); - writeU32(buf, heightmap_count); - os.write((char*)buf, 4); - - u32 heightmap_size = - FixedHeightmap::serializedLength(version, m_blocksize); - - SharedBuffer<u8> hmdata(heightmap_size); - - core::map<v2s16, FixedHeightmap*>::Iterator j; - j = m_heightmaps.getIterator(); - u32 i=0; - for(; j.atEnd() == false; j++) - { - v2s16 pos = j.getNode()->getKey(); - writeV2S16(buf, pos); - os.write((char*)buf, 4); - - FixedHeightmap *hm = j.getNode()->getValue(); - hm->serialize(*hmdata, version); - os.write((char*)*hmdata, hmdata.getSize()); - - i++; - } - } - else - { - // Write version - os.write((char*)&version, 1); - - u8 buf[4]; - - writeU16(buf, m_blocksize); - os.write((char*)buf, 2); - - /*m_randmax_generator->serialize(os); - m_randfactor_generator->serialize(os); - m_base_generator->serialize(os);*/ - - u32 heightmap_count = m_heightmaps.size(); - writeU32(buf, heightmap_count); - os.write((char*)buf, 4); - - u32 heightmap_size = - FixedHeightmap::serializedLength(version, m_blocksize); - - SharedBuffer<u8> hmdata(heightmap_size); - - core::map<v2s16, FixedHeightmap*>::Iterator j; - j = m_heightmaps.getIterator(); - u32 i=0; - for(; j.atEnd() == false; j++) - { - v2s16 pos = j.getNode()->getKey(); - writeV2S16(buf, pos); - os.write((char*)buf, 4); - - FixedHeightmap *hm = j.getNode()->getValue(); - hm->serialize(*hmdata, version); - os.write((char*)*hmdata, hmdata.getSize()); - - i++; - } - } - -#if 0 - if(version <= 7) - { - /*if(m_base_generator->getId() != VALUE_GENERATOR_ID_CONSTANT - || m_randmax_generator->getId() != VALUE_GENERATOR_ID_CONSTANT - || m_randfactor_generator->getId() != VALUE_GENERATOR_ID_CONSTANT)*/ - if(std::string(m_base_generator->getName()) != "constant" - || std::string(m_randmax_generator->getName()) != "constant" - || std::string(m_randfactor_generator->getName()) != "constant") - { - throw SerializationError - ("Cannot write UnlimitedHeightmap in old version: " - "Generators are not ConstantGenerators."); - } - - f32 basevalue = ((ConstantGenerator*)m_base_generator)->m_value; - f32 randmax = ((ConstantGenerator*)m_randmax_generator)->m_value; - f32 randfactor = ((ConstantGenerator*)m_randfactor_generator)->m_value; - - // Write version - os.write((char*)&version, 1); - - /* - [0] u16 blocksize - [2] s32 randmax*1000 - [6] s32 randfactor*1000 - [10] s32 basevalue*1000 - [14] u32 heightmap_count - [18] X * (v2s16 pos + heightmap) - */ - u32 heightmap_size = - FixedHeightmap::serializedLength(version, m_blocksize); - u32 heightmap_count = m_heightmaps.size(); - - //dstream<<"heightmap_size="<<heightmap_size<<std::endl; - - u32 datasize = 2+4+4+4+4+heightmap_count*(4+heightmap_size); - SharedBuffer<u8> data(datasize); - - writeU16(&data[0], m_blocksize); - writeU32(&data[2], (s32)(randmax*1000.0)); - writeU32(&data[6], (s32)(randfactor*1000.0)); - writeU32(&data[10], (s32)(basevalue*1000.0)); - writeU32(&data[14], heightmap_count); - - core::map<v2s16, FixedHeightmap*>::Iterator j; - j = m_heightmaps.getIterator(); - u32 i=0; - for(; j.atEnd() == false; j++) - { - FixedHeightmap *hm = j.getNode()->getValue(); - v2s16 pos = j.getNode()->getKey(); - writeV2S16(&data[18+i*(4+heightmap_size)], pos); - hm->serialize(&data[18+i*(4+heightmap_size)+4], version); - i++; - } - - os.write((char*)*data, data.getSize()); - } - else - { - // Write version - os.write((char*)&version, 1); - - u8 buf[4]; - - writeU16(buf, m_blocksize); - os.write((char*)buf, 2); - - /*m_randmax_generator->serialize(os, version); - m_randfactor_generator->serialize(os, version); - m_base_generator->serialize(os, version);*/ - m_randmax_generator->serialize(os); - m_randfactor_generator->serialize(os); - m_base_generator->serialize(os); - - u32 heightmap_count = m_heightmaps.size(); - writeU32(buf, heightmap_count); - os.write((char*)buf, 4); - - u32 heightmap_size = - FixedHeightmap::serializedLength(version, m_blocksize); - - SharedBuffer<u8> hmdata(heightmap_size); - - core::map<v2s16, FixedHeightmap*>::Iterator j; - j = m_heightmaps.getIterator(); - u32 i=0; - for(; j.atEnd() == false; j++) - { - v2s16 pos = j.getNode()->getKey(); - writeV2S16(buf, pos); - os.write((char*)buf, 4); - - FixedHeightmap *hm = j.getNode()->getValue(); - hm->serialize(*hmdata, version); - os.write((char*)*hmdata, hmdata.getSize()); - - i++; - } - } -#endif -} - -UnlimitedHeightmap * UnlimitedHeightmap::deSerialize(std::istream &is, - PointAttributeDatabase *padb) -{ - u8 version; - is.read((char*)&version, 1); - - if(!ser_ver_supported(version)) - throw VersionMismatchException("ERROR: UnlimitedHeightmap format not supported"); - - if(version <= 7) - { - /* - [0] u16 blocksize - [2] s32 randmax*1000 - [6] s32 randfactor*1000 - [10] s32 basevalue*1000 - [14] u32 heightmap_count - [18] X * (v2s16 pos + heightmap) - */ - SharedBuffer<u8> data(18); - is.read((char*)*data, 18); - if(is.gcount() != 18) - throw SerializationError - ("UnlimitedHeightmap::deSerialize: no enough input data"); - s16 blocksize = readU16(&data[0]); - // Dummy read randmax, randfactor, basevalue - /*f32 randmax = (f32)*/readU32(&data[2]) /*/ 1000.0*/; - /*f32 randfactor = (f32)*/readU32(&data[6]) /*/ 1000.0*/; - /*f32 basevalue = (f32)*/readU32(&data[10]) /*/ 1000.0*/; - u32 heightmap_count = readU32(&data[14]); - - /*dstream<<"UnlimitedHeightmap::deSerialize():" - <<" blocksize="<<blocksize - <<" heightmap_count="<<heightmap_count - <<std::endl;*/ - - u32 heightmap_size = - FixedHeightmap::serializedLength(version, blocksize); - - //dstream<<"heightmap_size="<<heightmap_size<<std::endl; - - /*ValueGenerator *maxgen = new ConstantGenerator(randmax); - ValueGenerator *factorgen = new ConstantGenerator(randfactor); - ValueGenerator *basegen = new ConstantGenerator(basevalue);*/ - - UnlimitedHeightmap *hm = new UnlimitedHeightmap - (blocksize, padb); - - for(u32 i=0; i<heightmap_count; i++) - { - //dstream<<"i="<<i<<std::endl; - SharedBuffer<u8> data(4+heightmap_size); - is.read((char*)*data, 4+heightmap_size); - if(is.gcount() != (s32)(4+heightmap_size)){ - delete hm; - throw SerializationError - ("UnlimitedHeightmap::deSerialize: no enough input data"); - } - v2s16 pos = readV2S16(&data[0]); - FixedHeightmap *f = new FixedHeightmap(hm, pos, blocksize); - f->deSerialize(&data[4], version); - hm->m_heightmaps.insert(pos, f); - } - return hm; - } - else if(version <= 11) - { - u8 buf[4]; - - is.read((char*)buf, 2); - s16 blocksize = readU16(buf); - - // Dummy-read three lines (generators) - std::string templine; - std::getline(is, templine, '\n'); - - is.read((char*)buf, 4); - u32 heightmap_count = readU32(buf); - - u32 heightmap_size = - FixedHeightmap::serializedLength(version, blocksize); - - UnlimitedHeightmap *hm = new UnlimitedHeightmap - (blocksize, padb); - - for(u32 i=0; i<heightmap_count; i++) - { - is.read((char*)buf, 4); - v2s16 pos = readV2S16(buf); - - SharedBuffer<u8> data(heightmap_size); - is.read((char*)*data, heightmap_size); - if(is.gcount() != (s32)(heightmap_size)){ - delete hm; - throw SerializationError - ("UnlimitedHeightmap::deSerialize: no enough input data"); - } - FixedHeightmap *f = new FixedHeightmap(hm, pos, blocksize); - f->deSerialize(*data, version); - hm->m_heightmaps.insert(pos, f); - } - return hm; - } - else - { - u8 buf[4]; - - is.read((char*)buf, 2); - s16 blocksize = readU16(buf); - - /*ValueGenerator *maxgen = ValueGenerator::deSerialize(is); - ValueGenerator *factorgen = ValueGenerator::deSerialize(is); - ValueGenerator *basegen = ValueGenerator::deSerialize(is);*/ - - is.read((char*)buf, 4); - u32 heightmap_count = readU32(buf); - - u32 heightmap_size = - FixedHeightmap::serializedLength(version, blocksize); - - UnlimitedHeightmap *hm = new UnlimitedHeightmap - (blocksize, padb); - - for(u32 i=0; i<heightmap_count; i++) - { - is.read((char*)buf, 4); - v2s16 pos = readV2S16(buf); - - SharedBuffer<u8> data(heightmap_size); - is.read((char*)*data, heightmap_size); - if(is.gcount() != (s32)(heightmap_size)){ - delete hm; - throw SerializationError - ("UnlimitedHeightmap::deSerialize: no enough input data"); - } - FixedHeightmap *f = new FixedHeightmap(hm, pos, blocksize); - f->deSerialize(*data, version); - hm->m_heightmaps.insert(pos, f); - } - return hm; - } -} - - |